1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3;
18  
19  import java.lang.reflect.Array;
20  import java.util.Arrays;
21  import java.util.BitSet;
22  import java.util.Comparator;
23  import java.util.HashMap;
24  import java.util.Map;
25  
26  import org.apache.commons.lang3.builder.EqualsBuilder;
27  import org.apache.commons.lang3.builder.HashCodeBuilder;
28  import org.apache.commons.lang3.builder.ToStringBuilder;
29  import org.apache.commons.lang3.builder.ToStringStyle;
30  import org.apache.commons.lang3.math.NumberUtils;
31  import org.apache.commons.lang3.mutable.MutableInt;
32  
33  /**
34   * <p>Operations on arrays, primitive arrays (like {@code int[]}) and
35   * primitive wrapper arrays (like {@code Integer[]}).</p>
36   *
37   * <p>This class tries to handle {@code null} input gracefully.
38   * An exception will not be thrown for a {@code null}
39   * array input. However, an Object array that contains a {@code null}
40   * element may throw an exception. Each method documents its behaviour.</p>
41   *
42   * <p>#ThreadSafe#</p>
43   * @since 2.0
44   * @version $Id$
45   */
46  public class ArrayUtils {
47  
48      /**
49       * An empty immutable {@code Object} array.
50       */
51      public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
52      /**
53       * An empty immutable {@code Class} array.
54       */
55      public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
56      /**
57       * An empty immutable {@code String} array.
58       */
59      public static final String[] EMPTY_STRING_ARRAY = new String[0];
60      /**
61       * An empty immutable {@code long} array.
62       */
63      public static final long[] EMPTY_LONG_ARRAY = new long[0];
64      /**
65       * An empty immutable {@code Long} array.
66       */
67      public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
68      /**
69       * An empty immutable {@code int} array.
70       */
71      public static final int[] EMPTY_INT_ARRAY = new int[0];
72      /**
73       * An empty immutable {@code Integer} array.
74       */
75      public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
76      /**
77       * An empty immutable {@code short} array.
78       */
79      public static final short[] EMPTY_SHORT_ARRAY = new short[0];
80      /**
81       * An empty immutable {@code Short} array.
82       */
83      public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
84      /**
85       * An empty immutable {@code byte} array.
86       */
87      public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
88      /**
89       * An empty immutable {@code Byte} array.
90       */
91      public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
92      /**
93       * An empty immutable {@code double} array.
94       */
95      public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
96      /**
97       * An empty immutable {@code Double} array.
98       */
99      public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
100     /**
101      * An empty immutable {@code float} array.
102      */
103     public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
104     /**
105      * An empty immutable {@code Float} array.
106      */
107     public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
108     /**
109      * An empty immutable {@code boolean} array.
110      */
111     public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
112     /**
113      * An empty immutable {@code Boolean} array.
114      */
115     public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
116     /**
117      * An empty immutable {@code char} array.
118      */
119     public static final char[] EMPTY_CHAR_ARRAY = new char[0];
120     /**
121      * An empty immutable {@code Character} array.
122      */
123     public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
124 
125     /**
126      * The index value when an element is not found in a list or array: {@code -1}.
127      * This value is returned by methods in this class and can also be used in comparisons with values returned by
128      * various method from {@link java.util.List}.
129      */
130     public static final int INDEX_NOT_FOUND = -1;
131 
132     /**
133      * <p>ArrayUtils instances should NOT be constructed in standard programming.
134      * Instead, the class should be used as <code>ArrayUtils.clone(new int[] {2})</code>.</p>
135      *
136      * <p>This constructor is public to permit tools that require a JavaBean instance
137      * to operate.</p>
138      */
139     public ArrayUtils() {
140       super();
141     }
142 
143 
144     // NOTE: Cannot use {@code} to enclose text which includes {}, but <code></code> is OK
145 
146 
147     // Basic methods handling multi-dimensional arrays
148     //-----------------------------------------------------------------------
149     /**
150      * <p>Outputs an array as a String, treating {@code null} as an empty array.</p>
151      *
152      * <p>Multi-dimensional arrays are handled correctly, including
153      * multi-dimensional primitive arrays.</p>
154      *
155      * <p>The format is that of Java source code, for example <code>{a,b}</code>.</p>
156      *
157      * @param array  the array to get a toString for, may be {@code null}
158      * @return a String representation of the array, '{}' if null array input
159      */
160     public static String toString(final Object array) {
161         return toString(array, "{}");
162     }
163 
164     /**
165      * <p>Outputs an array as a String handling {@code null}s.</p>
166      *
167      * <p>Multi-dimensional arrays are handled correctly, including
168      * multi-dimensional primitive arrays.</p>
169      *
170      * <p>The format is that of Java source code, for example <code>{a,b}</code>.</p>
171      *
172      * @param array  the array to get a toString for, may be {@code null}
173      * @param stringIfNull  the String to return if the array is {@code null}
174      * @return a String representation of the array
175      */
176     public static String toString(final Object array, final String stringIfNull) {
177         if (array == null) {
178             return stringIfNull;
179         }
180         return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
181     }
182 
183     /**
184      * <p>Get a hash code for an array handling multi-dimensional arrays correctly.</p>
185      *
186      * <p>Multi-dimensional primitive arrays are also handled correctly by this method.</p>
187      *
188      * @param array  the array to get a hash code for, {@code null} returns zero
189      * @return a hash code for the array
190      */
191     public static int hashCode(final Object array) {
192         return new HashCodeBuilder().append(array).toHashCode();
193     }
194 
195     /**
196      * <p>Compares two arrays, using equals(), handling multi-dimensional arrays
197      * correctly.</p>
198      *
199      * <p>Multi-dimensional primitive arrays are also handled correctly by this method.</p>
200      *
201      * @param array1  the left hand array to compare, may be {@code null}
202      * @param array2  the right hand array to compare, may be {@code null}
203      * @return {@code true} if the arrays are equal
204      * @deprecated this method has been replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
205      * removed from future releases.
206      */
207     @Deprecated
208     public static boolean isEquals(final Object array1, final Object array2) {
209         return new EqualsBuilder().append(array1, array2).isEquals();
210     }
211 
212     // To map
213     //-----------------------------------------------------------------------
214     /**
215      * <p>Converts the given array into a {@link java.util.Map}. Each element of the array
216      * must be either a {@link java.util.Map.Entry} or an Array, containing at least two
217      * elements, where the first element is used as key and the second as
218      * value.</p>
219      *
220      * <p>This method can be used to initialize:</p>
221      * <pre>
222      * // Create a Map mapping colors.
223      * Map colorMap = MapUtils.toMap(new String[][] {{
224      *     {"RED", "#FF0000"},
225      *     {"GREEN", "#00FF00"},
226      *     {"BLUE", "#0000FF"}});
227      * </pre>
228      *
229      * <p>This method returns {@code null} for a {@code null} input array.</p>
230      *
231      * @param array  an array whose elements are either a {@link java.util.Map.Entry} or
232      *  an Array containing at least two elements, may be {@code null}
233      * @return a {@code Map} that was created from the array
234      * @throws IllegalArgumentException  if one element of this Array is
235      *  itself an Array containing less then two elements
236      * @throws IllegalArgumentException  if the array contains elements other
237      *  than {@link java.util.Map.Entry} and an Array
238      */
239     public static Map<Object, Object> toMap(final Object[] array) {
240         if (array == null) {
241             return null;
242         }
243         final Map<Object, Object> map = new HashMap<Object, Object>((int) (array.length * 1.5));
244         for (int i = 0; i < array.length; i++) {
245             final Object object = array[i];
246             if (object instanceof Map.Entry<?, ?>) {
247                 final Map.Entry<?,?> entry = (Map.Entry<?,?>) object;
248                 map.put(entry.getKey(), entry.getValue());
249             } else if (object instanceof Object[]) {
250                 final Object[] entry = (Object[]) object;
251                 if (entry.length < 2) {
252                     throw new IllegalArgumentException("Array element " + i + ", '"
253                         + object
254                         + "', has a length less than 2");
255                 }
256                 map.put(entry[0], entry[1]);
257             } else {
258                 throw new IllegalArgumentException("Array element " + i + ", '"
259                         + object
260                         + "', is neither of type Map.Entry nor an Array");
261             }
262         }
263         return map;
264     }
265 
266     // Generic array
267     //-----------------------------------------------------------------------
268     /**
269      * <p>Create a type-safe generic array.</p>
270      *
271      * <p>The Java language does not allow an array to be created from a generic type:</p>
272      *
273      * <pre>
274     public static &lt;T&gt; T[] createAnArray(int size) {
275         return new T[size]; // compiler error here
276     }
277     public static &lt;T&gt; T[] createAnArray(int size) {
278         return (T[])new Object[size]; // ClassCastException at runtime
279     }
280      * </pre>
281      *
282      * <p>Therefore new arrays of generic types can be created with this method.
283      * For example, an array of Strings can be created:</p>
284      *
285      * <pre>
286     String[] array = ArrayUtils.toArray("1", "2");
287     String[] emptyArray = ArrayUtils.&lt;String&gt;toArray();
288      * </pre>
289      *
290      * <p>The method is typically used in scenarios, where the caller itself uses generic types
291      * that have to be combined into an array.</p>
292      *
293      * <p>Note, this method makes only sense to provide arguments of the same type so that the
294      * compiler can deduce the type of the array itself. While it is possible to select the
295      * type explicitly like in
296      * <code>Number[] array = ArrayUtils.&lt;Number&gt;toArray(Integer.valueOf(42), Double.valueOf(Math.PI))</code>,
297      * there is no real advantage when compared to
298      * <code>new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}</code>.</p>
299      *
300      * @param  <T>   the array's element type
301      * @param  items  the varargs array items, null allowed
302      * @return the array, not null unless a null array is passed in
303      * @since  3.0
304      */
305     public static <T> T[] toArray(final T... items) {
306         return items;
307     }
308 
309     // Clone
310     //-----------------------------------------------------------------------
311     /**
312      * <p>Shallow clones an array returning a typecast result and handling
313      * {@code null}.</p>
314      *
315      * <p>The objects in the array are not cloned, thus there is no special
316      * handling for multi-dimensional arrays.</p>
317      *
318      * <p>This method returns {@code null} for a {@code null} input array.</p>
319      *
320      * @param <T> the component type of the array
321      * @param array  the array to shallow clone, may be {@code null}
322      * @return the cloned array, {@code null} if {@code null} input
323      */
324     public static <T> T[] clone(final T[] array) {
325         if (array == null) {
326             return null;
327         }
328         return array.clone();
329     }
330 
331     /**
332      * <p>Clones an array returning a typecast result and handling
333      * {@code null}.</p>
334      *
335      * <p>This method returns {@code null} for a {@code null} input array.</p>
336      *
337      * @param array  the array to clone, may be {@code null}
338      * @return the cloned array, {@code null} if {@code null} input
339      */
340     public static long[] clone(final long[] array) {
341         if (array == null) {
342             return null;
343         }
344         return array.clone();
345     }
346 
347     /**
348      * <p>Clones an array returning a typecast result and handling
349      * {@code null}.</p>
350      *
351      * <p>This method returns {@code null} for a {@code null} input array.</p>
352      *
353      * @param array  the array to clone, may be {@code null}
354      * @return the cloned array, {@code null} if {@code null} input
355      */
356     public static int[] clone(final int[] array) {
357         if (array == null) {
358             return null;
359         }
360         return array.clone();
361     }
362 
363     /**
364      * <p>Clones an array returning a typecast result and handling
365      * {@code null}.</p>
366      *
367      * <p>This method returns {@code null} for a {@code null} input array.</p>
368      *
369      * @param array  the array to clone, may be {@code null}
370      * @return the cloned array, {@code null} if {@code null} input
371      */
372     public static short[] clone(final short[] array) {
373         if (array == null) {
374             return null;
375         }
376         return array.clone();
377     }
378 
379     /**
380      * <p>Clones an array returning a typecast result and handling
381      * {@code null}.</p>
382      *
383      * <p>This method returns {@code null} for a {@code null} input array.</p>
384      *
385      * @param array  the array to clone, may be {@code null}
386      * @return the cloned array, {@code null} if {@code null} input
387      */
388     public static char[] clone(final char[] array) {
389         if (array == null) {
390             return null;
391         }
392         return array.clone();
393     }
394 
395     /**
396      * <p>Clones an array returning a typecast result and handling
397      * {@code null}.</p>
398      *
399      * <p>This method returns {@code null} for a {@code null} input array.</p>
400      *
401      * @param array  the array to clone, may be {@code null}
402      * @return the cloned array, {@code null} if {@code null} input
403      */
404     public static byte[] clone(final byte[] array) {
405         if (array == null) {
406             return null;
407         }
408         return array.clone();
409     }
410 
411     /**
412      * <p>Clones an array returning a typecast result and handling
413      * {@code null}.</p>
414      *
415      * <p>This method returns {@code null} for a {@code null} input array.</p>
416      *
417      * @param array  the array to clone, may be {@code null}
418      * @return the cloned array, {@code null} if {@code null} input
419      */
420     public static double[] clone(final double[] array) {
421         if (array == null) {
422             return null;
423         }
424         return array.clone();
425     }
426 
427     /**
428      * <p>Clones an array returning a typecast result and handling
429      * {@code null}.</p>
430      *
431      * <p>This method returns {@code null} for a {@code null} input array.</p>
432      *
433      * @param array  the array to clone, may be {@code null}
434      * @return the cloned array, {@code null} if {@code null} input
435      */
436     public static float[] clone(final float[] array) {
437         if (array == null) {
438             return null;
439         }
440         return array.clone();
441     }
442 
443     /**
444      * <p>Clones an array returning a typecast result and handling
445      * {@code null}.</p>
446      *
447      * <p>This method returns {@code null} for a {@code null} input array.</p>
448      *
449      * @param array  the array to clone, may be {@code null}
450      * @return the cloned array, {@code null} if {@code null} input
451      */
452     public static boolean[] clone(final boolean[] array) {
453         if (array == null) {
454             return null;
455         }
456         return array.clone();
457     }
458 
459     // nullToEmpty
460     //-----------------------------------------------------------------------
461     /**
462      * <p>Defensive programming technique to change a {@code null}
463      * reference to an empty one.</p>
464      *
465      * <p>This method returns an empty array for a {@code null} input array.</p>
466      *
467      * <p>As a memory optimizing technique an empty array passed in will be overridden with
468      * the empty {@code public static} references in this class.</p>
469      *
470      * @param array  the array to check for {@code null} or empty
471      * @return the same array, {@code public static} empty array if {@code null} or empty input
472      * @since 2.5
473      */
474     public static Object[] nullToEmpty(final Object[] array) {
475         if (isEmpty(array)) {
476             return EMPTY_OBJECT_ARRAY;
477         }
478         return array;
479     }
480 
481     /**
482      * <p>Defensive programming technique to change a {@code null}
483      * reference to an empty one.</p>
484      *
485      * <p>This method returns an empty array for a {@code null} input array.</p>
486      *
487      * <p>As a memory optimizing technique an empty array passed in will be overridden with
488      * the empty {@code public static} references in this class.</p>
489      *
490      * @param array  the array to check for {@code null} or empty
491      * @return the same array, {@code public static} empty array if {@code null} or empty input
492      * @since 3.2
493      */
494     public static Class<?>[] nullToEmpty(final Class<?>[] array) {
495         if (isEmpty(array)) {
496             return EMPTY_CLASS_ARRAY;
497         }
498         return array;
499     }
500 
501     /**
502      * <p>Defensive programming technique to change a {@code null}
503      * reference to an empty one.</p>
504      *
505      * <p>This method returns an empty array for a {@code null} input array.</p>
506      *
507      * <p>As a memory optimizing technique an empty array passed in will be overridden with
508      * the empty {@code public static} references in this class.</p>
509      *
510      * @param array  the array to check for {@code null} or empty
511      * @return the same array, {@code public static} empty array if {@code null} or empty input
512      * @since 2.5
513      */
514     public static String[] nullToEmpty(final String[] array) {
515         if (isEmpty(array)) {
516             return EMPTY_STRING_ARRAY;
517         }
518         return array;
519     }
520 
521     /**
522      * <p>Defensive programming technique to change a {@code null}
523      * reference to an empty one.</p>
524      *
525      * <p>This method returns an empty array for a {@code null} input array.</p>
526      *
527      * <p>As a memory optimizing technique an empty array passed in will be overridden with
528      * the empty {@code public static} references in this class.</p>
529      *
530      * @param array  the array to check for {@code null} or empty
531      * @return the same array, {@code public static} empty array if {@code null} or empty input
532      * @since 2.5
533      */
534     public static long[] nullToEmpty(final long[] array) {
535         if (isEmpty(array)) {
536             return EMPTY_LONG_ARRAY;
537         }
538         return array;
539     }
540 
541     /**
542      * <p>Defensive programming technique to change a {@code null}
543      * reference to an empty one.</p>
544      *
545      * <p>This method returns an empty array for a {@code null} input array.</p>
546      *
547      * <p>As a memory optimizing technique an empty array passed in will be overridden with
548      * the empty {@code public static} references in this class.</p>
549      *
550      * @param array  the array to check for {@code null} or empty
551      * @return the same array, {@code public static} empty array if {@code null} or empty input
552      * @since 2.5
553      */
554     public static int[] nullToEmpty(final int[] array) {
555         if (isEmpty(array)) {
556             return EMPTY_INT_ARRAY;
557         }
558         return array;
559     }
560 
561     /**
562      * <p>Defensive programming technique to change a {@code null}
563      * reference to an empty one.</p>
564      *
565      * <p>This method returns an empty array for a {@code null} input array.</p>
566      *
567      * <p>As a memory optimizing technique an empty array passed in will be overridden with
568      * the empty {@code public static} references in this class.</p>
569      *
570      * @param array  the array to check for {@code null} or empty
571      * @return the same array, {@code public static} empty array if {@code null} or empty input
572      * @since 2.5
573      */
574     public static short[] nullToEmpty(final short[] array) {
575         if (isEmpty(array)) {
576             return EMPTY_SHORT_ARRAY;
577         }
578         return array;
579     }
580 
581     /**
582      * <p>Defensive programming technique to change a {@code null}
583      * reference to an empty one.</p>
584      *
585      * <p>This method returns an empty array for a {@code null} input array.</p>
586      *
587      * <p>As a memory optimizing technique an empty array passed in will be overridden with
588      * the empty {@code public static} references in this class.</p>
589      *
590      * @param array  the array to check for {@code null} or empty
591      * @return the same array, {@code public static} empty array if {@code null} or empty input
592      * @since 2.5
593      */
594     public static char[] nullToEmpty(final char[] array) {
595         if (isEmpty(array)) {
596             return EMPTY_CHAR_ARRAY;
597         }
598         return array;
599     }
600 
601     /**
602      * <p>Defensive programming technique to change a {@code null}
603      * reference to an empty one.</p>
604      *
605      * <p>This method returns an empty array for a {@code null} input array.</p>
606      *
607      * <p>As a memory optimizing technique an empty array passed in will be overridden with
608      * the empty {@code public static} references in this class.</p>
609      *
610      * @param array  the array to check for {@code null} or empty
611      * @return the same array, {@code public static} empty array if {@code null} or empty input
612      * @since 2.5
613      */
614     public static byte[] nullToEmpty(final byte[] array) {
615         if (isEmpty(array)) {
616             return EMPTY_BYTE_ARRAY;
617         }
618         return array;
619     }
620 
621     /**
622      * <p>Defensive programming technique to change a {@code null}
623      * reference to an empty one.</p>
624      *
625      * <p>This method returns an empty array for a {@code null} input array.</p>
626      *
627      * <p>As a memory optimizing technique an empty array passed in will be overridden with
628      * the empty {@code public static} references in this class.</p>
629      *
630      * @param array  the array to check for {@code null} or empty
631      * @return the same array, {@code public static} empty array if {@code null} or empty input
632      * @since 2.5
633      */
634     public static double[] nullToEmpty(final double[] array) {
635         if (isEmpty(array)) {
636             return EMPTY_DOUBLE_ARRAY;
637         }
638         return array;
639     }
640 
641     /**
642      * <p>Defensive programming technique to change a {@code null}
643      * reference to an empty one.</p>
644      *
645      * <p>This method returns an empty array for a {@code null} input array.</p>
646      *
647      * <p>As a memory optimizing technique an empty array passed in will be overridden with
648      * the empty {@code public static} references in this class.</p>
649      *
650      * @param array  the array to check for {@code null} or empty
651      * @return the same array, {@code public static} empty array if {@code null} or empty input
652      * @since 2.5
653      */
654     public static float[] nullToEmpty(final float[] array) {
655         if (isEmpty(array)) {
656             return EMPTY_FLOAT_ARRAY;
657         }
658         return array;
659     }
660 
661     /**
662      * <p>Defensive programming technique to change a {@code null}
663      * reference to an empty one.</p>
664      *
665      * <p>This method returns an empty array for a {@code null} input array.</p>
666      *
667      * <p>As a memory optimizing technique an empty array passed in will be overridden with
668      * the empty {@code public static} references in this class.</p>
669      *
670      * @param array  the array to check for {@code null} or empty
671      * @return the same array, {@code public static} empty array if {@code null} or empty input
672      * @since 2.5
673      */
674     public static boolean[] nullToEmpty(final boolean[] array) {
675         if (isEmpty(array)) {
676             return EMPTY_BOOLEAN_ARRAY;
677         }
678         return array;
679     }
680 
681     /**
682      * <p>Defensive programming technique to change a {@code null}
683      * reference to an empty one.</p>
684      *
685      * <p>This method returns an empty array for a {@code null} input array.</p>
686      *
687      * <p>As a memory optimizing technique an empty array passed in will be overridden with
688      * the empty {@code public static} references in this class.</p>
689      *
690      * @param array  the array to check for {@code null} or empty
691      * @return the same array, {@code public static} empty array if {@code null} or empty input
692      * @since 2.5
693      */
694     public static Long[] nullToEmpty(final Long[] array) {
695         if (isEmpty(array)) {
696             return EMPTY_LONG_OBJECT_ARRAY;
697         }
698         return array;
699     }
700 
701     /**
702      * <p>Defensive programming technique to change a {@code null}
703      * reference to an empty one.</p>
704      *
705      * <p>This method returns an empty array for a {@code null} input array.</p>
706      *
707      * <p>As a memory optimizing technique an empty array passed in will be overridden with
708      * the empty {@code public static} references in this class.</p>
709      *
710      * @param array  the array to check for {@code null} or empty
711      * @return the same array, {@code public static} empty array if {@code null} or empty input
712      * @since 2.5
713      */
714     public static Integer[] nullToEmpty(final Integer[] array) {
715         if (isEmpty(array)) {
716             return EMPTY_INTEGER_OBJECT_ARRAY;
717         }
718         return array;
719     }
720 
721     /**
722      * <p>Defensive programming technique to change a {@code null}
723      * reference to an empty one.</p>
724      *
725      * <p>This method returns an empty array for a {@code null} input array.</p>
726      *
727      * <p>As a memory optimizing technique an empty array passed in will be overridden with
728      * the empty {@code public static} references in this class.</p>
729      *
730      * @param array  the array to check for {@code null} or empty
731      * @return the same array, {@code public static} empty array if {@code null} or empty input
732      * @since 2.5
733      */
734     public static Short[] nullToEmpty(final Short[] array) {
735         if (isEmpty(array)) {
736             return EMPTY_SHORT_OBJECT_ARRAY;
737         }
738         return array;
739     }
740 
741     /**
742      * <p>Defensive programming technique to change a {@code null}
743      * reference to an empty one.</p>
744      *
745      * <p>This method returns an empty array for a {@code null} input array.</p>
746      *
747      * <p>As a memory optimizing technique an empty array passed in will be overridden with
748      * the empty {@code public static} references in this class.</p>
749      *
750      * @param array  the array to check for {@code null} or empty
751      * @return the same array, {@code public static} empty array if {@code null} or empty input
752      * @since 2.5
753      */
754     public static Character[] nullToEmpty(final Character[] array) {
755         if (isEmpty(array)) {
756             return EMPTY_CHARACTER_OBJECT_ARRAY;
757         }
758         return array;
759     }
760 
761     /**
762      * <p>Defensive programming technique to change a {@code null}
763      * reference to an empty one.</p>
764      *
765      * <p>This method returns an empty array for a {@code null} input array.</p>
766      *
767      * <p>As a memory optimizing technique an empty array passed in will be overridden with
768      * the empty {@code public static} references in this class.</p>
769      *
770      * @param array  the array to check for {@code null} or empty
771      * @return the same array, {@code public static} empty array if {@code null} or empty input
772      * @since 2.5
773      */
774     public static Byte[] nullToEmpty(final Byte[] array) {
775         if (isEmpty(array)) {
776             return EMPTY_BYTE_OBJECT_ARRAY;
777         }
778         return array;
779     }
780 
781     /**
782      * <p>Defensive programming technique to change a {@code null}
783      * reference to an empty one.</p>
784      *
785      * <p>This method returns an empty array for a {@code null} input array.</p>
786      *
787      * <p>As a memory optimizing technique an empty array passed in will be overridden with
788      * the empty {@code public static} references in this class.</p>
789      *
790      * @param array  the array to check for {@code null} or empty
791      * @return the same array, {@code public static} empty array if {@code null} or empty input
792      * @since 2.5
793      */
794     public static Double[] nullToEmpty(final Double[] array) {
795         if (isEmpty(array)) {
796             return EMPTY_DOUBLE_OBJECT_ARRAY;
797         }
798         return array;
799     }
800 
801     /**
802      * <p>Defensive programming technique to change a {@code null}
803      * reference to an empty one.</p>
804      *
805      * <p>This method returns an empty array for a {@code null} input array.</p>
806      *
807      * <p>As a memory optimizing technique an empty array passed in will be overridden with
808      * the empty {@code public static} references in this class.</p>
809      *
810      * @param array  the array to check for {@code null} or empty
811      * @return the same array, {@code public static} empty array if {@code null} or empty input
812      * @since 2.5
813      */
814     public static Float[] nullToEmpty(final Float[] array) {
815         if (isEmpty(array)) {
816             return EMPTY_FLOAT_OBJECT_ARRAY;
817         }
818         return array;
819     }
820 
821     /**
822      * <p>Defensive programming technique to change a {@code null}
823      * reference to an empty one.</p>
824      *
825      * <p>This method returns an empty array for a {@code null} input array.</p>
826      *
827      * <p>As a memory optimizing technique an empty array passed in will be overridden with
828      * the empty {@code public static} references in this class.</p>
829      *
830      * @param array  the array to check for {@code null} or empty
831      * @return the same array, {@code public static} empty array if {@code null} or empty input
832      * @since 2.5
833      */
834     public static Boolean[] nullToEmpty(final Boolean[] array) {
835         if (isEmpty(array)) {
836             return EMPTY_BOOLEAN_OBJECT_ARRAY;
837         }
838         return array;
839     }
840 
841     // Subarrays
842     //-----------------------------------------------------------------------
843     /**
844      * <p>Produces a new array containing the elements between
845      * the start and end indices.</p>
846      *
847      * <p>The start index is inclusive, the end index exclusive.
848      * Null array input produces null output.</p>
849      *
850      * <p>The component type of the subarray is always the same as
851      * that of the input array. Thus, if the input is an array of type
852      * {@code Date}, the following usage is envisaged:</p>
853      *
854      * <pre>
855      * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);
856      * </pre>
857      *
858      * @param <T> the component type of the array
859      * @param array  the array
860      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
861      *      is promoted to 0, overvalue (&gt;array.length) results
862      *      in an empty array.
863      * @param endIndexExclusive  elements up to endIndex-1 are present in the
864      *      returned subarray. Undervalue (&lt; startIndex) produces
865      *      empty array, overvalue (&gt;array.length) is demoted to
866      *      array length.
867      * @return a new array containing the elements between
868      *      the start and end indices.
869      * @since 2.1
870      * @see Arrays#copyOfRange(Object[], int, int)
871      */
872     public static <T> T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {
873         if (array == null) {
874             return null;
875         }
876         if (startIndexInclusive < 0) {
877             startIndexInclusive = 0;
878         }
879         if (endIndexExclusive > array.length) {
880             endIndexExclusive = array.length;
881         }
882         final int newSize = endIndexExclusive - startIndexInclusive;
883         final Class<?> type = array.getClass().getComponentType();
884         if (newSize <= 0) {
885             @SuppressWarnings("unchecked") // OK, because array is of type T
886             final T[] emptyArray = (T[]) Array.newInstance(type, 0);
887             return emptyArray;
888         }
889         @SuppressWarnings("unchecked") // OK, because array is of type T
890         final
891         T[] subarray = (T[]) Array.newInstance(type, newSize);
892         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
893         return subarray;
894     }
895 
896     /**
897      * <p>Produces a new {@code long} array containing the elements
898      * between the start and end indices.</p>
899      *
900      * <p>The start index is inclusive, the end index exclusive.
901      * Null array input produces null output.</p>
902      *
903      * @param array  the array
904      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
905      *      is promoted to 0, overvalue (&gt;array.length) results
906      *      in an empty array.
907      * @param endIndexExclusive  elements up to endIndex-1 are present in the
908      *      returned subarray. Undervalue (&lt; startIndex) produces
909      *      empty array, overvalue (&gt;array.length) is demoted to
910      *      array length.
911      * @return a new array containing the elements between
912      *      the start and end indices.
913      * @since 2.1
914      * @see Arrays#copyOfRange(long[], int, int)
915      */
916     public static long[] subarray(final long[] array, int startIndexInclusive, int endIndexExclusive) {
917         if (array == null) {
918             return null;
919         }
920         if (startIndexInclusive < 0) {
921             startIndexInclusive = 0;
922         }
923         if (endIndexExclusive > array.length) {
924             endIndexExclusive = array.length;
925         }
926         final int newSize = endIndexExclusive - startIndexInclusive;
927         if (newSize <= 0) {
928             return EMPTY_LONG_ARRAY;
929         }
930 
931         final long[] subarray = new long[newSize];
932         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
933         return subarray;
934     }
935 
936     /**
937      * <p>Produces a new {@code int} array containing the elements
938      * between the start and end indices.</p>
939      *
940      * <p>The start index is inclusive, the end index exclusive.
941      * Null array input produces null output.</p>
942      *
943      * @param array  the array
944      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
945      *      is promoted to 0, overvalue (&gt;array.length) results
946      *      in an empty array.
947      * @param endIndexExclusive  elements up to endIndex-1 are present in the
948      *      returned subarray. Undervalue (&lt; startIndex) produces
949      *      empty array, overvalue (&gt;array.length) is demoted to
950      *      array length.
951      * @return a new array containing the elements between
952      *      the start and end indices.
953      * @since 2.1
954      * @see Arrays#copyOfRange(int[], int, int)
955      */
956     public static int[] subarray(final int[] array, int startIndexInclusive, int endIndexExclusive) {
957         if (array == null) {
958             return null;
959         }
960         if (startIndexInclusive < 0) {
961             startIndexInclusive = 0;
962         }
963         if (endIndexExclusive > array.length) {
964             endIndexExclusive = array.length;
965         }
966         final int newSize = endIndexExclusive - startIndexInclusive;
967         if (newSize <= 0) {
968             return EMPTY_INT_ARRAY;
969         }
970 
971         final int[] subarray = new int[newSize];
972         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
973         return subarray;
974     }
975 
976     /**
977      * <p>Produces a new {@code short} array containing the elements
978      * between the start and end indices.</p>
979      *
980      * <p>The start index is inclusive, the end index exclusive.
981      * Null array input produces null output.</p>
982      *
983      * @param array  the array
984      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
985      *      is promoted to 0, overvalue (&gt;array.length) results
986      *      in an empty array.
987      * @param endIndexExclusive  elements up to endIndex-1 are present in the
988      *      returned subarray. Undervalue (&lt; startIndex) produces
989      *      empty array, overvalue (&gt;array.length) is demoted to
990      *      array length.
991      * @return a new array containing the elements between
992      *      the start and end indices.
993      * @since 2.1
994      * @see Arrays#copyOfRange(short[], int, int)
995      */
996     public static short[] subarray(final short[] array, int startIndexInclusive, int endIndexExclusive) {
997         if (array == null) {
998             return null;
999         }
1000         if (startIndexInclusive < 0) {
1001             startIndexInclusive = 0;
1002         }
1003         if (endIndexExclusive > array.length) {
1004             endIndexExclusive = array.length;
1005         }
1006         final int newSize = endIndexExclusive - startIndexInclusive;
1007         if (newSize <= 0) {
1008             return EMPTY_SHORT_ARRAY;
1009         }
1010 
1011         final short[] subarray = new short[newSize];
1012         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1013         return subarray;
1014     }
1015 
1016     /**
1017      * <p>Produces a new {@code char} array containing the elements
1018      * between the start and end indices.</p>
1019      *
1020      * <p>The start index is inclusive, the end index exclusive.
1021      * Null array input produces null output.</p>
1022      *
1023      * @param array  the array
1024      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1025      *      is promoted to 0, overvalue (&gt;array.length) results
1026      *      in an empty array.
1027      * @param endIndexExclusive  elements up to endIndex-1 are present in the
1028      *      returned subarray. Undervalue (&lt; startIndex) produces
1029      *      empty array, overvalue (&gt;array.length) is demoted to
1030      *      array length.
1031      * @return a new array containing the elements between
1032      *      the start and end indices.
1033      * @since 2.1
1034      * @see Arrays#copyOfRange(char[], int, int)
1035      */
1036     public static char[] subarray(final char[] array, int startIndexInclusive, int endIndexExclusive) {
1037         if (array == null) {
1038             return null;
1039         }
1040         if (startIndexInclusive < 0) {
1041             startIndexInclusive = 0;
1042         }
1043         if (endIndexExclusive > array.length) {
1044             endIndexExclusive = array.length;
1045         }
1046         final int newSize = endIndexExclusive - startIndexInclusive;
1047         if (newSize <= 0) {
1048             return EMPTY_CHAR_ARRAY;
1049         }
1050 
1051         final char[] subarray = new char[newSize];
1052         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1053         return subarray;
1054     }
1055 
1056     /**
1057      * <p>Produces a new {@code byte} array containing the elements
1058      * between the start and end indices.</p>
1059      *
1060      * <p>The start index is inclusive, the end index exclusive.
1061      * Null array input produces null output.</p>
1062      *
1063      * @param array  the array
1064      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1065      *      is promoted to 0, overvalue (&gt;array.length) results
1066      *      in an empty array.
1067      * @param endIndexExclusive  elements up to endIndex-1 are present in the
1068      *      returned subarray. Undervalue (&lt; startIndex) produces
1069      *      empty array, overvalue (&gt;array.length) is demoted to
1070      *      array length.
1071      * @return a new array containing the elements between
1072      *      the start and end indices.
1073      * @since 2.1
1074      * @see Arrays#copyOfRange(byte[], int, int)
1075      */
1076     public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
1077         if (array == null) {
1078             return null;
1079         }
1080         if (startIndexInclusive < 0) {
1081             startIndexInclusive = 0;
1082         }
1083         if (endIndexExclusive > array.length) {
1084             endIndexExclusive = array.length;
1085         }
1086         final int newSize = endIndexExclusive - startIndexInclusive;
1087         if (newSize <= 0) {
1088             return EMPTY_BYTE_ARRAY;
1089         }
1090 
1091         final byte[] subarray = new byte[newSize];
1092         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1093         return subarray;
1094     }
1095 
1096     /**
1097      * <p>Produces a new {@code double} array containing the elements
1098      * between the start and end indices.</p>
1099      *
1100      * <p>The start index is inclusive, the end index exclusive.
1101      * Null array input produces null output.</p>
1102      *
1103      * @param array  the array
1104      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1105      *      is promoted to 0, overvalue (&gt;array.length) results
1106      *      in an empty array.
1107      * @param endIndexExclusive  elements up to endIndex-1 are present in the
1108      *      returned subarray. Undervalue (&lt; startIndex) produces
1109      *      empty array, overvalue (&gt;array.length) is demoted to
1110      *      array length.
1111      * @return a new array containing the elements between
1112      *      the start and end indices.
1113      * @since 2.1
1114      * @see Arrays#copyOfRange(double[], int, int)
1115      */
1116     public static double[] subarray(final double[] array, int startIndexInclusive, int endIndexExclusive) {
1117         if (array == null) {
1118             return null;
1119         }
1120         if (startIndexInclusive < 0) {
1121             startIndexInclusive = 0;
1122         }
1123         if (endIndexExclusive > array.length) {
1124             endIndexExclusive = array.length;
1125         }
1126         final int newSize = endIndexExclusive - startIndexInclusive;
1127         if (newSize <= 0) {
1128             return EMPTY_DOUBLE_ARRAY;
1129         }
1130 
1131         final double[] subarray = new double[newSize];
1132         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1133         return subarray;
1134     }
1135 
1136     /**
1137      * <p>Produces a new {@code float} array containing the elements
1138      * between the start and end indices.</p>
1139      *
1140      * <p>The start index is inclusive, the end index exclusive.
1141      * Null array input produces null output.</p>
1142      *
1143      * @param array  the array
1144      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1145      *      is promoted to 0, overvalue (&gt;array.length) results
1146      *      in an empty array.
1147      * @param endIndexExclusive  elements up to endIndex-1 are present in the
1148      *      returned subarray. Undervalue (&lt; startIndex) produces
1149      *      empty array, overvalue (&gt;array.length) is demoted to
1150      *      array length.
1151      * @return a new array containing the elements between
1152      *      the start and end indices.
1153      * @since 2.1
1154      * @see Arrays#copyOfRange(float[], int, int)
1155      */
1156     public static float[] subarray(final float[] array, int startIndexInclusive, int endIndexExclusive) {
1157         if (array == null) {
1158             return null;
1159         }
1160         if (startIndexInclusive < 0) {
1161             startIndexInclusive = 0;
1162         }
1163         if (endIndexExclusive > array.length) {
1164             endIndexExclusive = array.length;
1165         }
1166         final int newSize = endIndexExclusive - startIndexInclusive;
1167         if (newSize <= 0) {
1168             return EMPTY_FLOAT_ARRAY;
1169         }
1170 
1171         final float[] subarray = new float[newSize];
1172         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1173         return subarray;
1174     }
1175 
1176     /**
1177      * <p>Produces a new {@code boolean} array containing the elements
1178      * between the start and end indices.</p>
1179      *
1180      * <p>The start index is inclusive, the end index exclusive.
1181      * Null array input produces null output.</p>
1182      *
1183      * @param array  the array
1184      * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1185      *      is promoted to 0, overvalue (&gt;array.length) results
1186      *      in an empty array.
1187      * @param endIndexExclusive  elements up to endIndex-1 are present in the
1188      *      returned subarray. Undervalue (&lt; startIndex) produces
1189      *      empty array, overvalue (&gt;array.length) is demoted to
1190      *      array length.
1191      * @return a new array containing the elements between
1192      *      the start and end indices.
1193      * @since 2.1
1194      * @see Arrays#copyOfRange(boolean[], int, int)
1195      */
1196     public static boolean[] subarray(final boolean[] array, int startIndexInclusive, int endIndexExclusive) {
1197         if (array == null) {
1198             return null;
1199         }
1200         if (startIndexInclusive < 0) {
1201             startIndexInclusive = 0;
1202         }
1203         if (endIndexExclusive > array.length) {
1204             endIndexExclusive = array.length;
1205         }
1206         final int newSize = endIndexExclusive - startIndexInclusive;
1207         if (newSize <= 0) {
1208             return EMPTY_BOOLEAN_ARRAY;
1209         }
1210 
1211         final boolean[] subarray = new boolean[newSize];
1212         System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1213         return subarray;
1214     }
1215 
1216     // Is same length
1217     //-----------------------------------------------------------------------
1218     /**
1219      * <p>Checks whether two arrays are the same length, treating
1220      * {@code null} arrays as length {@code 0}.
1221      *
1222      * <p>Any multi-dimensional aspects of the arrays are ignored.</p>
1223      *
1224      * @param array1 the first array, may be {@code null}
1225      * @param array2 the second array, may be {@code null}
1226      * @return {@code true} if length of arrays matches, treating
1227      *  {@code null} as an empty array
1228      */
1229     public static boolean isSameLength(final Object[] array1, final Object[] array2) {
1230         if ((array1 == null && array2 != null && array2.length > 0) ||
1231             (array2 == null && array1 != null && array1.length > 0) ||
1232             (array1 != null && array2 != null && array1.length != array2.length)) {
1233                 return false;
1234         }
1235         return true;
1236     }
1237 
1238     /**
1239      * <p>Checks whether two arrays are the same length, treating
1240      * {@code null} arrays as length {@code 0}.</p>
1241      *
1242      * @param array1 the first array, may be {@code null}
1243      * @param array2 the second array, may be {@code null}
1244      * @return {@code true} if length of arrays matches, treating
1245      *  {@code null} as an empty array
1246      */
1247     public static boolean isSameLength(final long[] array1, final long[] array2) {
1248         if ((array1 == null && array2 != null && array2.length > 0) ||
1249             (array2 == null && array1 != null && array1.length > 0) ||
1250             (array1 != null && array2 != null && array1.length != array2.length)) {
1251                 return false;
1252         }
1253         return true;
1254     }
1255 
1256     /**
1257      * <p>Checks whether two arrays are the same length, treating
1258      * {@code null} arrays as length {@code 0}.</p>
1259      *
1260      * @param array1 the first array, may be {@code null}
1261      * @param array2 the second array, may be {@code null}
1262      * @return {@code true} if length of arrays matches, treating
1263      *  {@code null} as an empty array
1264      */
1265     public static boolean isSameLength(final int[] array1, final int[] array2) {
1266         if ((array1 == null && array2 != null && array2.length > 0) ||
1267             (array2 == null && array1 != null && array1.length > 0) ||
1268             (array1 != null && array2 != null && array1.length != array2.length)) {
1269                 return false;
1270         }
1271         return true;
1272     }
1273 
1274     /**
1275      * <p>Checks whether two arrays are the same length, treating
1276      * {@code null} arrays as length {@code 0}.</p>
1277      *
1278      * @param array1 the first array, may be {@code null}
1279      * @param array2 the second array, may be {@code null}
1280      * @return {@code true} if length of arrays matches, treating
1281      *  {@code null} as an empty array
1282      */
1283     public static boolean isSameLength(final short[] array1, final short[] array2) {
1284         if ((array1 == null && array2 != null && array2.length > 0) ||
1285             (array2 == null && array1 != null && array1.length > 0) ||
1286             (array1 != null && array2 != null && array1.length != array2.length)) {
1287                 return false;
1288         }
1289         return true;
1290     }
1291 
1292     /**
1293      * <p>Checks whether two arrays are the same length, treating
1294      * {@code null} arrays as length {@code 0}.</p>
1295      *
1296      * @param array1 the first array, may be {@code null}
1297      * @param array2 the second array, may be {@code null}
1298      * @return {@code true} if length of arrays matches, treating
1299      *  {@code null} as an empty array
1300      */
1301     public static boolean isSameLength(final char[] array1, final char[] array2) {
1302         if ((array1 == null && array2 != null && array2.length > 0) ||
1303             (array2 == null && array1 != null && array1.length > 0) ||
1304             (array1 != null && array2 != null && array1.length != array2.length)) {
1305                 return false;
1306         }
1307         return true;
1308     }
1309 
1310     /**
1311      * <p>Checks whether two arrays are the same length, treating
1312      * {@code null} arrays as length {@code 0}.</p>
1313      *
1314      * @param array1 the first array, may be {@code null}
1315      * @param array2 the second array, may be {@code null}
1316      * @return {@code true} if length of arrays matches, treating
1317      *  {@code null} as an empty array
1318      */
1319     public static boolean isSameLength(final byte[] array1, final byte[] array2) {
1320         if ((array1 == null && array2 != null && array2.length > 0) ||
1321             (array2 == null && array1 != null && array1.length > 0) ||
1322             (array1 != null && array2 != null && array1.length != array2.length)) {
1323                 return false;
1324         }
1325         return true;
1326     }
1327 
1328     /**
1329      * <p>Checks whether two arrays are the same length, treating
1330      * {@code null} arrays as length {@code 0}.</p>
1331      *
1332      * @param array1 the first array, may be {@code null}
1333      * @param array2 the second array, may be {@code null}
1334      * @return {@code true} if length of arrays matches, treating
1335      *  {@code null} as an empty array
1336      */
1337     public static boolean isSameLength(final double[] array1, final double[] array2) {
1338         if ((array1 == null && array2 != null && array2.length > 0) ||
1339             (array2 == null && array1 != null && array1.length > 0) ||
1340             (array1 != null && array2 != null && array1.length != array2.length)) {
1341                 return false;
1342         }
1343         return true;
1344     }
1345 
1346     /**
1347      * <p>Checks whether two arrays are the same length, treating
1348      * {@code null} arrays as length {@code 0}.</p>
1349      *
1350      * @param array1 the first array, may be {@code null}
1351      * @param array2 the second array, may be {@code null}
1352      * @return {@code true} if length of arrays matches, treating
1353      *  {@code null} as an empty array
1354      */
1355     public static boolean isSameLength(final float[] array1, final float[] array2) {
1356         if ((array1 == null && array2 != null && array2.length > 0) ||
1357             (array2 == null && array1 != null && array1.length > 0) ||
1358             (array1 != null && array2 != null && array1.length != array2.length)) {
1359                 return false;
1360         }
1361         return true;
1362     }
1363 
1364     /**
1365      * <p>Checks whether two arrays are the same length, treating
1366      * {@code null} arrays as length {@code 0}.</p>
1367      *
1368      * @param array1 the first array, may be {@code null}
1369      * @param array2 the second array, may be {@code null}
1370      * @return {@code true} if length of arrays matches, treating
1371      *  {@code null} as an empty array
1372      */
1373     public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
1374         if ((array1 == null && array2 != null && array2.length > 0) ||
1375             (array2 == null && array1 != null && array1.length > 0) ||
1376             (array1 != null && array2 != null && array1.length != array2.length)) {
1377                 return false;
1378         }
1379         return true;
1380     }
1381 
1382     //-----------------------------------------------------------------------
1383     /**
1384      * <p>Returns the length of the specified array.
1385      * This method can deal with {@code Object} arrays and with primitive arrays.</p>
1386      *
1387      * <p>If the input array is {@code null}, {@code 0} is returned.</p>
1388      *
1389      * <pre>
1390      * ArrayUtils.getLength(null)            = 0
1391      * ArrayUtils.getLength([])              = 0
1392      * ArrayUtils.getLength([null])          = 1
1393      * ArrayUtils.getLength([true, false])   = 2
1394      * ArrayUtils.getLength([1, 2, 3])       = 3
1395      * ArrayUtils.getLength(["a", "b", "c"]) = 3
1396      * </pre>
1397      *
1398      * @param array  the array to retrieve the length from, may be null
1399      * @return The length of the array, or {@code 0} if the array is {@code null}
1400      * @throws IllegalArgumentException if the object argument is not an array.
1401      * @since 2.1
1402      */
1403     public static int getLength(final Object array) {
1404         if (array == null) {
1405             return 0;
1406         }
1407         return Array.getLength(array);
1408     }
1409 
1410     /**
1411      * <p>Checks whether two arrays are the same type taking into account
1412      * multi-dimensional arrays.</p>
1413      *
1414      * @param array1 the first array, must not be {@code null}
1415      * @param array2 the second array, must not be {@code null}
1416      * @return {@code true} if type of arrays matches
1417      * @throws IllegalArgumentException if either array is {@code null}
1418      */
1419     public static boolean isSameType(final Object array1, final Object array2) {
1420         if (array1 == null || array2 == null) {
1421             throw new IllegalArgumentException("The Array must not be null");
1422         }
1423         return array1.getClass().getName().equals(array2.getClass().getName());
1424     }
1425 
1426     // Reverse
1427     //-----------------------------------------------------------------------
1428     /**
1429      * <p>Reverses the order of the given array.</p>
1430      *
1431      * <p>There is no special handling for multi-dimensional arrays.</p>
1432      *
1433      * <p>This method does nothing for a {@code null} input array.</p>
1434      *
1435      * @param array  the array to reverse, may be {@code null}
1436      */
1437     public static void reverse(final Object[] array) {
1438         if (array == null) {
1439             return;
1440         }
1441         reverse(array, 0, array.length);
1442     }
1443 
1444     /**
1445      * <p>Reverses the order of the given array.</p>
1446      *
1447      * <p>This method does nothing for a {@code null} input array.</p>
1448      *
1449      * @param array  the array to reverse, may be {@code null}
1450      */
1451     public static void reverse(final long[] array) {
1452         if (array == null) {
1453             return;
1454         }
1455         reverse(array, 0, array.length);
1456     }
1457 
1458     /**
1459      * <p>Reverses the order of the given array.</p>
1460      *
1461      * <p>This method does nothing for a {@code null} input array.</p>
1462      *
1463      * @param array  the array to reverse, may be {@code null}
1464      */
1465     public static void reverse(final int[] array) {
1466         if (array == null) {
1467             return;
1468         }
1469         reverse(array, 0, array.length);
1470     }
1471 
1472     /**
1473      * <p>Reverses the order of the given array.</p>
1474      *
1475      * <p>This method does nothing for a {@code null} input array.</p>
1476      *
1477      * @param array  the array to reverse, may be {@code null}
1478      */
1479     public static void reverse(final short[] array) {
1480         if (array == null) {
1481             return;
1482         }
1483         reverse(array, 0, array.length);
1484     }
1485 
1486     /**
1487      * <p>Reverses the order of the given array.</p>
1488      *
1489      * <p>This method does nothing for a {@code null} input array.</p>
1490      *
1491      * @param array  the array to reverse, may be {@code null}
1492      */
1493     public static void reverse(final char[] array) {
1494         if (array == null) {
1495             return;
1496         }
1497         reverse(array, 0, array.length);
1498     }
1499 
1500     /**
1501      * <p>Reverses the order of the given array.</p>
1502      *
1503      * <p>This method does nothing for a {@code null} input array.</p>
1504      *
1505      * @param array  the array to reverse, may be {@code null}
1506      */
1507     public static void reverse(final byte[] array) {
1508         if (array == null) {
1509             return;
1510         }
1511         reverse(array, 0, array.length);
1512     }
1513 
1514     /**
1515      * <p>Reverses the order of the given array.</p>
1516      *
1517      * <p>This method does nothing for a {@code null} input array.</p>
1518      *
1519      * @param array  the array to reverse, may be {@code null}
1520      */
1521     public static void reverse(final double[] array) {
1522         if (array == null) {
1523             return;
1524         }
1525         reverse(array, 0, array.length);
1526     }
1527 
1528     /**
1529      * <p>Reverses the order of the given array.</p>
1530      *
1531      * <p>This method does nothing for a {@code null} input array.</p>
1532      *
1533      * @param array  the array to reverse, may be {@code null}
1534      */
1535     public static void reverse(final float[] array) {
1536         if (array == null) {
1537             return;
1538         }
1539         reverse(array, 0, array.length);
1540     }
1541 
1542     /**
1543      * <p>Reverses the order of the given array.</p>
1544      *
1545      * <p>This method does nothing for a {@code null} input array.</p>
1546      *
1547      * @param array  the array to reverse, may be {@code null}
1548      */
1549     public static void reverse(final boolean[] array) {
1550         if (array == null) {
1551             return;
1552         }
1553         reverse(array, 0, array.length);
1554     }
1555 
1556     /**
1557      * <p>
1558      * Reverses the order of the given array in the given range.
1559      * </p>
1560      * 
1561      * <p>
1562      * This method does nothing for a {@code null} input array.
1563      * </p>
1564      * 
1565      * @param array
1566      *            the array to reverse, may be {@code null}
1567      * @param startIndexInclusive
1568      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1569      *            change.
1570      * @param endIndexExclusive
1571      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1572      *            change. Overvalue (&gt;array.length) is demoted to array length.
1573      * @since 3.2
1574      */
1575     public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
1576         if (array == null) {
1577             return;
1578         }
1579         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1580         int j = Math.min(array.length, endIndexExclusive) - 1;
1581         boolean tmp;
1582         while (j > i) {
1583             tmp = array[j];
1584             array[j] = array[i];
1585             array[i] = tmp;
1586             j--;
1587             i++;
1588         }
1589     }
1590 
1591     /**
1592      * <p>
1593      * Reverses the order of the given array in the given range.
1594      * </p>
1595      * 
1596      * <p>
1597      * This method does nothing for a {@code null} input array.
1598      * </p>
1599      * 
1600      * @param array
1601      *            the array to reverse, may be {@code null}
1602      * @param startIndexInclusive
1603      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1604      *            change.
1605      * @param endIndexExclusive
1606      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1607      *            change. Overvalue (&gt;array.length) is demoted to array length.
1608      * @since 3.2
1609      */
1610     public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
1611         if (array == null) {
1612             return;
1613         }
1614         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1615         int j = Math.min(array.length, endIndexExclusive) - 1;
1616         byte tmp;
1617         while (j > i) {
1618             tmp = array[j];
1619             array[j] = array[i];
1620             array[i] = tmp;
1621             j--;
1622             i++;
1623         }
1624     }
1625 
1626     /**
1627      * <p>
1628      * Reverses the order of the given array in the given range.
1629      * </p>
1630      * 
1631      * <p>
1632      * This method does nothing for a {@code null} input array.
1633      * </p>
1634      * 
1635      * @param array
1636      *            the array to reverse, may be {@code null}
1637      * @param startIndexInclusive
1638      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1639      *            change.
1640      * @param endIndexExclusive
1641      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1642      *            change. Overvalue (&gt;array.length) is demoted to array length.
1643      * @since 3.2
1644      */
1645     public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
1646         if (array == null) {
1647             return;
1648         }
1649         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1650         int j = Math.min(array.length, endIndexExclusive) - 1;
1651         char tmp;
1652         while (j > i) {
1653             tmp = array[j];
1654             array[j] = array[i];
1655             array[i] = tmp;
1656             j--;
1657             i++;
1658         }
1659     }
1660 
1661     /**
1662      * <p>
1663      * Reverses the order of the given array in the given range.
1664      * </p>
1665      * 
1666      * <p>
1667      * This method does nothing for a {@code null} input array.
1668      * </p>
1669      * 
1670      * @param array
1671      *            the array to reverse, may be {@code null}
1672      * @param startIndexInclusive
1673      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1674      *            change.
1675      * @param endIndexExclusive
1676      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1677      *            change. Overvalue (&gt;array.length) is demoted to array length.
1678      * @since 3.2
1679      */
1680     public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
1681         if (array == null) {
1682             return;
1683         }
1684         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1685         int j = Math.min(array.length, endIndexExclusive) - 1;
1686         double tmp;
1687         while (j > i) {
1688             tmp = array[j];
1689             array[j] = array[i];
1690             array[i] = tmp;
1691             j--;
1692             i++;
1693         }
1694     }
1695 
1696     /**
1697      * <p>
1698      * Reverses the order of the given array in the given range.
1699      * </p>
1700      * 
1701      * <p>
1702      * This method does nothing for a {@code null} input array.
1703      * </p>
1704      * 
1705      * @param array
1706      *            the array to reverse, may be {@code null}
1707      * @param startIndexInclusive
1708      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1709      *            change.
1710      * @param endIndexExclusive
1711      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1712      *            change. Overvalue (&gt;array.length) is demoted to array length.
1713      * @since 3.2
1714      */
1715     public static void reverse(final float[] array, final int startIndexInclusive, final int endIndexExclusive) {
1716         if (array == null) {
1717             return;
1718         }
1719         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1720         int j = Math.min(array.length, endIndexExclusive) - 1;
1721         float tmp;
1722         while (j > i) {
1723             tmp = array[j];
1724             array[j] = array[i];
1725             array[i] = tmp;
1726             j--;
1727             i++;
1728         }
1729     }
1730 
1731     /**
1732      * <p>
1733      * Reverses the order of the given array in the given range.
1734      * </p>
1735      * 
1736      * <p>
1737      * This method does nothing for a {@code null} input array.
1738      * </p>
1739      * 
1740      * @param array
1741      *            the array to reverse, may be {@code null}
1742      * @param startIndexInclusive
1743      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1744      *            change.
1745      * @param endIndexExclusive
1746      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1747      *            change. Overvalue (&gt;array.length) is demoted to array length.
1748      * @since 3.2
1749      */
1750     public static void reverse(final int[] array, final int startIndexInclusive, final int endIndexExclusive) {
1751         if (array == null) {
1752             return;
1753         }
1754         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1755         int j = Math.min(array.length, endIndexExclusive) - 1;
1756         int tmp;
1757         while (j > i) {
1758             tmp = array[j];
1759             array[j] = array[i];
1760             array[i] = tmp;
1761             j--;
1762             i++;
1763         }
1764     }
1765 
1766     /**
1767      * <p>
1768      * Reverses the order of the given array in the given range.
1769      * </p>
1770      * 
1771      * <p>
1772      * This method does nothing for a {@code null} input array.
1773      * </p>
1774      * 
1775      * @param array
1776      *            the array to reverse, may be {@code null}
1777      * @param startIndexInclusive
1778      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1779      *            change.
1780      * @param endIndexExclusive
1781      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1782      *            change. Overvalue (&gt;array.length) is demoted to array length.
1783      * @since 3.2
1784      */
1785     public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
1786         if (array == null) {
1787             return;
1788         }
1789         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1790         int j = Math.min(array.length, endIndexExclusive) - 1;
1791         long tmp;
1792         while (j > i) {
1793             tmp = array[j];
1794             array[j] = array[i];
1795             array[i] = tmp;
1796             j--;
1797             i++;
1798         }
1799     }
1800 
1801     /**
1802      * <p>
1803      * Reverses the order of the given array in the given range.
1804      * </p>
1805      * 
1806      * <p>
1807      * This method does nothing for a {@code null} input array.
1808      * </p>
1809      * 
1810      * @param array
1811      *            the array to reverse, may be {@code null}
1812      * @param startIndexInclusive
1813      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1814      *            change.
1815      * @param endIndexExclusive
1816      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1817      *            change. Overvalue (&gt;array.length) is demoted to array length.
1818      * @since 3.2
1819      */
1820     public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) {
1821         if (array == null) {
1822             return;
1823         }
1824         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1825         int j = Math.min(array.length, endIndexExclusive) - 1;
1826         Object tmp;
1827         while (j > i) {
1828             tmp = array[j];
1829             array[j] = array[i];
1830             array[i] = tmp;
1831             j--;
1832             i++;
1833         }
1834     }
1835 
1836     /**
1837      * <p>
1838      * Reverses the order of the given array in the given range.
1839      * </p>
1840      * 
1841      * <p>
1842      * This method does nothing for a {@code null} input array.
1843      * </p>
1844      * 
1845      * @param array
1846      *            the array to reverse, may be {@code null}
1847      * @param startIndexInclusive
1848      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1849      *            change.
1850      * @param endIndexExclusive
1851      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1852      *            change. Overvalue (&gt;array.length) is demoted to array length.
1853      * @since 3.2
1854      */
1855     public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
1856         if (array == null) {
1857             return;
1858         }
1859         int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1860         int j = Math.min(array.length, endIndexExclusive) - 1;
1861         short tmp;
1862         while (j > i) {
1863             tmp = array[j];
1864             array[j] = array[i];
1865             array[i] = tmp;
1866             j--;
1867             i++;
1868         }
1869     }
1870 
1871     // IndexOf search
1872     // ----------------------------------------------------------------------
1873 
1874     // Object IndexOf
1875     //-----------------------------------------------------------------------
1876     /**
1877      * <p>Finds the index of the given object in the array.</p>
1878      *
1879      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1880      *
1881      * @param array  the array to search through for the object, may be {@code null}
1882      * @param objectToFind  the object to find, may be {@code null}
1883      * @return the index of the object within the array,
1884      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1885      */
1886     public static int indexOf(final Object[] array, final Object objectToFind) {
1887         return indexOf(array, objectToFind, 0);
1888     }
1889 
1890     /**
1891      * <p>Finds the index of the given object in the array starting at the given index.</p>
1892      *
1893      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1894      *
1895      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1896      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
1897      *
1898      * @param array  the array to search through for the object, may be {@code null}
1899      * @param objectToFind  the object to find, may be {@code null}
1900      * @param startIndex  the index to start searching at
1901      * @return the index of the object within the array starting at the index,
1902      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1903      */
1904     public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
1905         if (array == null) {
1906             return INDEX_NOT_FOUND;
1907         }
1908         if (startIndex < 0) {
1909             startIndex = 0;
1910         }
1911         if (objectToFind == null) {
1912             for (int i = startIndex; i < array.length; i++) {
1913                 if (array[i] == null) {
1914                     return i;
1915                 }
1916             }
1917         } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
1918             for (int i = startIndex; i < array.length; i++) {
1919                 if (objectToFind.equals(array[i])) {
1920                     return i;
1921                 }
1922             }
1923         }
1924         return INDEX_NOT_FOUND;
1925     }
1926 
1927     /**
1928      * <p>Finds the last index of the given object within the array.</p>
1929      *
1930      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1931      *
1932      * @param array  the array to travers backwords looking for the object, may be {@code null}
1933      * @param objectToFind  the object to find, may be {@code null}
1934      * @return the last index of the object within the array,
1935      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1936      */
1937     public static int lastIndexOf(final Object[] array, final Object objectToFind) {
1938         return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
1939     }
1940 
1941     /**
1942      * <p>Finds the last index of the given object in the array starting at the given index.</p>
1943      *
1944      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1945      *
1946      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
1947      * the array length will search from the end of the array.</p>
1948      *
1949      * @param array  the array to traverse for looking for the object, may be {@code null}
1950      * @param objectToFind  the object to find, may be {@code null}
1951      * @param startIndex  the start index to travers backwards from
1952      * @return the last index of the object within the array,
1953      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1954      */
1955     public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
1956         if (array == null) {
1957             return INDEX_NOT_FOUND;
1958         }
1959         if (startIndex < 0) {
1960             return INDEX_NOT_FOUND;
1961         } else if (startIndex >= array.length) {
1962             startIndex = array.length - 1;
1963         }
1964         if (objectToFind == null) {
1965             for (int i = startIndex; i >= 0; i--) {
1966                 if (array[i] == null) {
1967                     return i;
1968                 }
1969             }
1970         } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
1971             for (int i = startIndex; i >= 0; i--) {
1972                 if (objectToFind.equals(array[i])) {
1973                     return i;
1974                 }
1975             }
1976         }
1977         return INDEX_NOT_FOUND;
1978     }
1979 
1980     /**
1981      * <p>Checks if the object is in the given array.</p>
1982      *
1983      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
1984      *
1985      * @param array  the array to search through
1986      * @param objectToFind  the object to find
1987      * @return {@code true} if the array contains the object
1988      */
1989     public static boolean contains(final Object[] array, final Object objectToFind) {
1990         return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
1991     }
1992 
1993     // long IndexOf
1994     //-----------------------------------------------------------------------
1995     /**
1996      * <p>Finds the index of the given value in the array.</p>
1997      *
1998      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1999      *
2000      * @param array  the array to search through for the object, may be {@code null}
2001      * @param valueToFind  the value to find
2002      * @return the index of the value within the array,
2003      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2004      */
2005     public static int indexOf(final long[] array, final long valueToFind) {
2006         return indexOf(array, valueToFind, 0);
2007     }
2008 
2009     /**
2010      * <p>Finds the index of the given value in the array starting at the given index.</p>
2011      *
2012      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2013      *
2014      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2015      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2016      *
2017      * @param array  the array to search through for the object, may be {@code null}
2018      * @param valueToFind  the value to find
2019      * @param startIndex  the index to start searching at
2020      * @return the index of the value within the array,
2021      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2022      */
2023     public static int indexOf(final long[] array, final long valueToFind, int startIndex) {
2024         if (array == null) {
2025             return INDEX_NOT_FOUND;
2026         }
2027         if (startIndex < 0) {
2028             startIndex = 0;
2029         }
2030         for (int i = startIndex; i < array.length; i++) {
2031             if (valueToFind == array[i]) {
2032                 return i;
2033             }
2034         }
2035         return INDEX_NOT_FOUND;
2036     }
2037 
2038     /**
2039      * <p>Finds the last index of the given value within the array.</p>
2040      *
2041      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2042      *
2043      * @param array  the array to travers backwords looking for the object, may be {@code null}
2044      * @param valueToFind  the object to find
2045      * @return the last index of the value within the array,
2046      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2047      */
2048     public static int lastIndexOf(final long[] array, final long valueToFind) {
2049         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2050     }
2051 
2052     /**
2053      * <p>Finds the last index of the given value in the array starting at the given index.</p>
2054      *
2055      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2056      *
2057      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2058      * array length will search from the end of the array.</p>
2059      *
2060      * @param array  the array to traverse for looking for the object, may be {@code null}
2061      * @param valueToFind  the value to find
2062      * @param startIndex  the start index to travers backwards from
2063      * @return the last index of the value within the array,
2064      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2065      */
2066     public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
2067         if (array == null) {
2068             return INDEX_NOT_FOUND;
2069         }
2070         if (startIndex < 0) {
2071             return INDEX_NOT_FOUND;
2072         } else if (startIndex >= array.length) {
2073             startIndex = array.length - 1;
2074         }
2075         for (int i = startIndex; i >= 0; i--) {
2076             if (valueToFind == array[i]) {
2077                 return i;
2078             }
2079         }
2080         return INDEX_NOT_FOUND;
2081     }
2082 
2083     /**
2084      * <p>Checks if the value is in the given array.</p>
2085      *
2086      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2087      *
2088      * @param array  the array to search through
2089      * @param valueToFind  the value to find
2090      * @return {@code true} if the array contains the object
2091      */
2092     public static boolean contains(final long[] array, final long valueToFind) {
2093         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2094     }
2095 
2096     // int IndexOf
2097     //-----------------------------------------------------------------------
2098     /**
2099      * <p>Finds the index of the given value in the array.</p>
2100      *
2101      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2102      *
2103      * @param array  the array to search through for the object, may be {@code null}
2104      * @param valueToFind  the value to find
2105      * @return the index of the value within the array,
2106      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2107      */
2108     public static int indexOf(final int[] array, final int valueToFind) {
2109         return indexOf(array, valueToFind, 0);
2110     }
2111 
2112     /**
2113      * <p>Finds the index of the given value in the array starting at the given index.</p>
2114      *
2115      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2116      *
2117      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2118      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2119      *
2120      * @param array  the array to search through for the object, may be {@code null}
2121      * @param valueToFind  the value to find
2122      * @param startIndex  the index to start searching at
2123      * @return the index of the value within the array,
2124      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2125      */
2126     public static int indexOf(final int[] array, final int valueToFind, int startIndex) {
2127         if (array == null) {
2128             return INDEX_NOT_FOUND;
2129         }
2130         if (startIndex < 0) {
2131             startIndex = 0;
2132         }
2133         for (int i = startIndex; i < array.length; i++) {
2134             if (valueToFind == array[i]) {
2135                 return i;
2136             }
2137         }
2138         return INDEX_NOT_FOUND;
2139     }
2140 
2141     /**
2142      * <p>Finds the last index of the given value within the array.</p>
2143      *
2144      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2145      *
2146      * @param array  the array to travers backwords looking for the object, may be {@code null}
2147      * @param valueToFind  the object to find
2148      * @return the last index of the value within the array,
2149      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2150      */
2151     public static int lastIndexOf(final int[] array, final int valueToFind) {
2152         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2153     }
2154 
2155     /**
2156      * <p>Finds the last index of the given value in the array starting at the given index.</p>
2157      *
2158      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2159      *
2160      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2161      * array length will search from the end of the array.</p>
2162      *
2163      * @param array  the array to traverse for looking for the object, may be {@code null}
2164      * @param valueToFind  the value to find
2165      * @param startIndex  the start index to travers backwards from
2166      * @return the last index of the value within the array,
2167      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2168      */
2169     public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
2170         if (array == null) {
2171             return INDEX_NOT_FOUND;
2172         }
2173         if (startIndex < 0) {
2174             return INDEX_NOT_FOUND;
2175         } else if (startIndex >= array.length) {
2176             startIndex = array.length - 1;
2177         }
2178         for (int i = startIndex; i >= 0; i--) {
2179             if (valueToFind == array[i]) {
2180                 return i;
2181             }
2182         }
2183         return INDEX_NOT_FOUND;
2184     }
2185 
2186     /**
2187      * <p>Checks if the value is in the given array.</p>
2188      *
2189      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2190      *
2191      * @param array  the array to search through
2192      * @param valueToFind  the value to find
2193      * @return {@code true} if the array contains the object
2194      */
2195     public static boolean contains(final int[] array, final int valueToFind) {
2196         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2197     }
2198 
2199     // short IndexOf
2200     //-----------------------------------------------------------------------
2201     /**
2202      * <p>Finds the index of the given value in the array.</p>
2203      *
2204      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2205      *
2206      * @param array  the array to search through for the object, may be {@code null}
2207      * @param valueToFind  the value to find
2208      * @return the index of the value within the array,
2209      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2210      */
2211     public static int indexOf(final short[] array, final short valueToFind) {
2212         return indexOf(array, valueToFind, 0);
2213     }
2214 
2215     /**
2216      * <p>Finds the index of the given value in the array starting at the given index.</p>
2217      *
2218      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2219      *
2220      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2221      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2222      *
2223      * @param array  the array to search through for the object, may be {@code null}
2224      * @param valueToFind  the value to find
2225      * @param startIndex  the index to start searching at
2226      * @return the index of the value within the array,
2227      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2228      */
2229     public static int indexOf(final short[] array, final short valueToFind, int startIndex) {
2230         if (array == null) {
2231             return INDEX_NOT_FOUND;
2232         }
2233         if (startIndex < 0) {
2234             startIndex = 0;
2235         }
2236         for (int i = startIndex; i < array.length; i++) {
2237             if (valueToFind == array[i]) {
2238                 return i;
2239             }
2240         }
2241         return INDEX_NOT_FOUND;
2242     }
2243 
2244     /**
2245      * <p>Finds the last index of the given value within the array.</p>
2246      *
2247      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2248      *
2249      * @param array  the array to travers backwords looking for the object, may be {@code null}
2250      * @param valueToFind  the object to find
2251      * @return the last index of the value within the array,
2252      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2253      */
2254     public static int lastIndexOf(final short[] array, final short valueToFind) {
2255         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2256     }
2257 
2258     /**
2259      * <p>Finds the last index of the given value in the array starting at the given index.</p>
2260      *
2261      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2262      *
2263      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2264      * array length will search from the end of the array.</p>
2265      *
2266      * @param array  the array to traverse for looking for the object, may be {@code null}
2267      * @param valueToFind  the value to find
2268      * @param startIndex  the start index to travers backwards from
2269      * @return the last index of the value within the array,
2270      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2271      */
2272     public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
2273         if (array == null) {
2274             return INDEX_NOT_FOUND;
2275         }
2276         if (startIndex < 0) {
2277             return INDEX_NOT_FOUND;
2278         } else if (startIndex >= array.length) {
2279             startIndex = array.length - 1;
2280         }
2281         for (int i = startIndex; i >= 0; i--) {
2282             if (valueToFind == array[i]) {
2283                 return i;
2284             }
2285         }
2286         return INDEX_NOT_FOUND;
2287     }
2288 
2289     /**
2290      * <p>Checks if the value is in the given array.</p>
2291      *
2292      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2293      *
2294      * @param array  the array to search through
2295      * @param valueToFind  the value to find
2296      * @return {@code true} if the array contains the object
2297      */
2298     public static boolean contains(final short[] array, final short valueToFind) {
2299         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2300     }
2301 
2302     // char IndexOf
2303     //-----------------------------------------------------------------------
2304     /**
2305      * <p>Finds the index of the given value in the array.</p>
2306      *
2307      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2308      *
2309      * @param array  the array to search through for the object, may be {@code null}
2310      * @param valueToFind  the value to find
2311      * @return the index of the value within the array,
2312      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2313      * @since 2.1
2314      */
2315     public static int indexOf(final char[] array, final char valueToFind) {
2316         return indexOf(array, valueToFind, 0);
2317     }
2318 
2319     /**
2320      * <p>Finds the index of the given value in the array starting at the given index.</p>
2321      *
2322      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2323      *
2324      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2325      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2326      *
2327      * @param array  the array to search through for the object, may be {@code null}
2328      * @param valueToFind  the value to find
2329      * @param startIndex  the index to start searching at
2330      * @return the index of the value within the array,
2331      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2332      * @since 2.1
2333      */
2334     public static int indexOf(final char[] array, final char valueToFind, int startIndex) {
2335         if (array == null) {
2336             return INDEX_NOT_FOUND;
2337         }
2338         if (startIndex < 0) {
2339             startIndex = 0;
2340         }
2341         for (int i = startIndex; i < array.length; i++) {
2342             if (valueToFind == array[i]) {
2343                 return i;
2344             }
2345         }
2346         return INDEX_NOT_FOUND;
2347     }
2348 
2349     /**
2350      * <p>Finds the last index of the given value within the array.</p>
2351      *
2352      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2353      *
2354      * @param array  the array to travers backwords looking for the object, may be {@code null}
2355      * @param valueToFind  the object to find
2356      * @return the last index of the value within the array,
2357      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2358      * @since 2.1
2359      */
2360     public static int lastIndexOf(final char[] array, final char valueToFind) {
2361         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2362     }
2363 
2364     /**
2365      * <p>Finds the last index of the given value in the array starting at the given index.</p>
2366      *
2367      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2368      *
2369      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2370      * array length will search from the end of the array.</p>
2371      *
2372      * @param array  the array to traverse for looking for the object, may be {@code null}
2373      * @param valueToFind  the value to find
2374      * @param startIndex  the start index to travers backwards from
2375      * @return the last index of the value within the array,
2376      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2377      * @since 2.1
2378      */
2379     public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
2380         if (array == null) {
2381             return INDEX_NOT_FOUND;
2382         }
2383         if (startIndex < 0) {
2384             return INDEX_NOT_FOUND;
2385         } else if (startIndex >= array.length) {
2386             startIndex = array.length - 1;
2387         }
2388         for (int i = startIndex; i >= 0; i--) {
2389             if (valueToFind == array[i]) {
2390                 return i;
2391             }
2392         }
2393         return INDEX_NOT_FOUND;
2394     }
2395 
2396     /**
2397      * <p>Checks if the value is in the given array.</p>
2398      *
2399      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2400      *
2401      * @param array  the array to search through
2402      * @param valueToFind  the value to find
2403      * @return {@code true} if the array contains the object
2404      * @since 2.1
2405      */
2406     public static boolean contains(final char[] array, final char valueToFind) {
2407         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2408     }
2409 
2410     // byte IndexOf
2411     //-----------------------------------------------------------------------
2412     /**
2413      * <p>Finds the index of the given value in the array.</p>
2414      *
2415      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2416      *
2417      * @param array  the array to search through for the object, may be {@code null}
2418      * @param valueToFind  the value to find
2419      * @return the index of the value within the array,
2420      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2421      */
2422     public static int indexOf(final byte[] array, final byte valueToFind) {
2423         return indexOf(array, valueToFind, 0);
2424     }
2425 
2426     /**
2427      * <p>Finds the index of the given value in the array starting at the given index.</p>
2428      *
2429      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2430      *
2431      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2432      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2433      *
2434      * @param array  the array to search through for the object, may be {@code null}
2435      * @param valueToFind  the value to find
2436      * @param startIndex  the index to start searching at
2437      * @return the index of the value within the array,
2438      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2439      */
2440     public static int indexOf(final byte[] array, final byte valueToFind, int startIndex) {
2441         if (array == null) {
2442             return INDEX_NOT_FOUND;
2443         }
2444         if (startIndex < 0) {
2445             startIndex = 0;
2446         }
2447         for (int i = startIndex; i < array.length; i++) {
2448             if (valueToFind == array[i]) {
2449                 return i;
2450             }
2451         }
2452         return INDEX_NOT_FOUND;
2453     }
2454 
2455     /**
2456      * <p>Finds the last index of the given value within the array.</p>
2457      *
2458      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2459      *
2460      * @param array  the array to travers backwords looking for the object, may be {@code null}
2461      * @param valueToFind  the object to find
2462      * @return the last index of the value within the array,
2463      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2464      */
2465     public static int lastIndexOf(final byte[] array, final byte valueToFind) {
2466         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2467     }
2468 
2469     /**
2470      * <p>Finds the last index of the given value in the array starting at the given index.</p>
2471      *
2472      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2473      *
2474      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2475      * array length will search from the end of the array.</p>
2476      *
2477      * @param array  the array to traverse for looking for the object, may be {@code null}
2478      * @param valueToFind  the value to find
2479      * @param startIndex  the start index to travers backwards from
2480      * @return the last index of the value within the array,
2481      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2482      */
2483     public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
2484         if (array == null) {
2485             return INDEX_NOT_FOUND;
2486         }
2487         if (startIndex < 0) {
2488             return INDEX_NOT_FOUND;
2489         } else if (startIndex >= array.length) {
2490             startIndex = array.length - 1;
2491         }
2492         for (int i = startIndex; i >= 0; i--) {
2493             if (valueToFind == array[i]) {
2494                 return i;
2495             }
2496         }
2497         return INDEX_NOT_FOUND;
2498     }
2499 
2500     /**
2501      * <p>Checks if the value is in the given array.</p>
2502      *
2503      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2504      *
2505      * @param array  the array to search through
2506      * @param valueToFind  the value to find
2507      * @return {@code true} if the array contains the object
2508      */
2509     public static boolean contains(final byte[] array, final byte valueToFind) {
2510         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2511     }
2512 
2513     // double IndexOf
2514     //-----------------------------------------------------------------------
2515     /**
2516      * <p>Finds the index of the given value in the array.</p>
2517      *
2518      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2519      *
2520      * @param array  the array to search through for the object, may be {@code null}
2521      * @param valueToFind  the value to find
2522      * @return the index of the value within the array,
2523      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2524      */
2525     public static int indexOf(final double[] array, final double valueToFind) {
2526         return indexOf(array, valueToFind, 0);
2527     }
2528 
2529     /**
2530      * <p>Finds the index of the given value within a given tolerance in the array.
2531      * This method will return the index of the first value which falls between the region
2532      * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
2533      *
2534      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2535      *
2536      * @param array  the array to search through for the object, may be {@code null}
2537      * @param valueToFind  the value to find
2538      * @param tolerance tolerance of the search
2539      * @return the index of the value within the array,
2540      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2541      */
2542     public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
2543         return indexOf(array, valueToFind, 0, tolerance);
2544     }
2545 
2546     /**
2547      * <p>Finds the index of the given value in the array starting at the given index.</p>
2548      *
2549      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2550      *
2551      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2552      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2553      *
2554      * @param array  the array to search through for the object, may be {@code null}
2555      * @param valueToFind  the value to find
2556      * @param startIndex  the index to start searching at
2557      * @return the index of the value within the array,
2558      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2559      */
2560     public static int indexOf(final double[] array, final double valueToFind, int startIndex) {
2561         if (ArrayUtils.isEmpty(array)) {
2562             return INDEX_NOT_FOUND;
2563         }
2564         if (startIndex < 0) {
2565             startIndex = 0;
2566         }
2567         for (int i = startIndex; i < array.length; i++) {
2568             if (valueToFind == array[i]) {
2569                 return i;
2570             }
2571         }
2572         return INDEX_NOT_FOUND;
2573     }
2574 
2575     /**
2576      * <p>Finds the index of the given value in the array starting at the given index.
2577      * This method will return the index of the first value which falls between the region
2578      * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
2579      *
2580      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2581      *
2582      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2583      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2584      *
2585      * @param array  the array to search through for the object, may be {@code null}
2586      * @param valueToFind  the value to find
2587      * @param startIndex  the index to start searching at
2588      * @param tolerance tolerance of the search
2589      * @return the index of the value within the array,
2590      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2591      */
2592     public static int indexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
2593         if (ArrayUtils.isEmpty(array)) {
2594             return INDEX_NOT_FOUND;
2595         }
2596         if (startIndex < 0) {
2597             startIndex = 0;
2598         }
2599         final double min = valueToFind - tolerance;
2600         final double max = valueToFind + tolerance;
2601         for (int i = startIndex; i < array.length; i++) {
2602             if (array[i] >= min && array[i] <= max) {
2603                 return i;
2604             }
2605         }
2606         return INDEX_NOT_FOUND;
2607     }
2608 
2609     /**
2610      * <p>Finds the last index of the given value within the array.</p>
2611      *
2612      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2613      *
2614      * @param array  the array to travers backwords looking for the object, may be {@code null}
2615      * @param valueToFind  the object to find
2616      * @return the last index of the value within the array,
2617      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2618      */
2619     public static int lastIndexOf(final double[] array, final double valueToFind) {
2620         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2621     }
2622 
2623     /**
2624      * <p>Finds the last index of the given value within a given tolerance in the array.
2625      * This method will return the index of the last value which falls between the region
2626      * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
2627      *
2628      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2629      *
2630      * @param array  the array to search through for the object, may be {@code null}
2631      * @param valueToFind  the value to find
2632      * @param tolerance tolerance of the search
2633      * @return the index of the value within the array,
2634      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2635      */
2636     public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
2637         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
2638     }
2639 
2640     /**
2641      * <p>Finds the last index of the given value in the array starting at the given index.</p>
2642      *
2643      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2644      *
2645      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2646      * array length will search from the end of the array.</p>
2647      *
2648      * @param array  the array to traverse for looking for the object, may be {@code null}
2649      * @param valueToFind  the value to find
2650      * @param startIndex  the start index to travers backwards from
2651      * @return the last index of the value within the array,
2652      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2653      */
2654     public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
2655         if (ArrayUtils.isEmpty(array)) {
2656             return INDEX_NOT_FOUND;
2657         }
2658         if (startIndex < 0) {
2659             return INDEX_NOT_FOUND;
2660         } else if (startIndex >= array.length) {
2661             startIndex = array.length - 1;
2662         }
2663         for (int i = startIndex; i >= 0; i--) {
2664             if (valueToFind == array[i]) {
2665                 return i;
2666             }
2667         }
2668         return INDEX_NOT_FOUND;
2669     }
2670 
2671     /**
2672      * <p>Finds the last index of the given value in the array starting at the given index.
2673      * This method will return the index of the last value which falls between the region
2674      * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
2675      *
2676      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2677      *
2678      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2679      * array length will search from the end of the array.</p>
2680      *
2681      * @param array  the array to traverse for looking for the object, may be {@code null}
2682      * @param valueToFind  the value to find
2683      * @param startIndex  the start index to travers backwards from
2684      * @param tolerance  search for value within plus/minus this amount
2685      * @return the last index of the value within the array,
2686      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2687      */
2688     public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
2689         if (ArrayUtils.isEmpty(array)) {
2690             return INDEX_NOT_FOUND;
2691         }
2692         if (startIndex < 0) {
2693             return INDEX_NOT_FOUND;
2694         } else if (startIndex >= array.length) {
2695             startIndex = array.length - 1;
2696         }
2697         final double min = valueToFind - tolerance;
2698         final double max = valueToFind + tolerance;
2699         for (int i = startIndex; i >= 0; i--) {
2700             if (array[i] >= min && array[i] <= max) {
2701                 return i;
2702             }
2703         }
2704         return INDEX_NOT_FOUND;
2705     }
2706 
2707     /**
2708      * <p>Checks if the value is in the given array.</p>
2709      *
2710      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2711      *
2712      * @param array  the array to search through
2713      * @param valueToFind  the value to find
2714      * @return {@code true} if the array contains the object
2715      */
2716     public static boolean contains(final double[] array, final double valueToFind) {
2717         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2718     }
2719 
2720     /**
2721      * <p>Checks if a value falling within the given tolerance is in the
2722      * given array.  If the array contains a value within the inclusive range
2723      * defined by (value - tolerance) to (value + tolerance).</p>
2724      *
2725      * <p>The method returns {@code false} if a {@code null} array
2726      * is passed in.</p>
2727      *
2728      * @param array  the array to search
2729      * @param valueToFind  the value to find
2730      * @param tolerance  the array contains the tolerance of the search
2731      * @return true if value falling within tolerance is in array
2732      */
2733     public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
2734         return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
2735     }
2736 
2737     // float IndexOf
2738     //-----------------------------------------------------------------------
2739     /**
2740      * <p>Finds the index of the given value in the array.</p>
2741      *
2742      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2743      *
2744      * @param array  the array to search through for the object, may be {@code null}
2745      * @param valueToFind  the value to find
2746      * @return the index of the value within the array,
2747      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2748      */
2749     public static int indexOf(final float[] array, final float valueToFind) {
2750         return indexOf(array, valueToFind, 0);
2751     }
2752 
2753     /**
2754      * <p>Finds the index of the given value in the array starting at the given index.</p>
2755      *
2756      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2757      *
2758      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2759      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2760      *
2761      * @param array  the array to search through for the object, may be {@code null}
2762      * @param valueToFind  the value to find
2763      * @param startIndex  the index to start searching at
2764      * @return the index of the value within the array,
2765      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2766      */
2767     public static int indexOf(final float[] array, final float valueToFind, int startIndex) {
2768         if (ArrayUtils.isEmpty(array)) {
2769             return INDEX_NOT_FOUND;
2770         }
2771         if (startIndex < 0) {
2772             startIndex = 0;
2773         }
2774         for (int i = startIndex; i < array.length; i++) {
2775             if (valueToFind == array[i]) {
2776                 return i;
2777             }
2778         }
2779         return INDEX_NOT_FOUND;
2780     }
2781 
2782     /**
2783      * <p>Finds the last index of the given value within the array.</p>
2784      *
2785      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2786      *
2787      * @param array  the array to travers backwords looking for the object, may be {@code null}
2788      * @param valueToFind  the object to find
2789      * @return the last index of the value within the array,
2790      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2791      */
2792     public static int lastIndexOf(final float[] array, final float valueToFind) {
2793         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2794     }
2795 
2796     /**
2797      * <p>Finds the last index of the given value in the array starting at the given index.</p>
2798      *
2799      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2800      *
2801      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2802      * array length will search from the end of the array.</p>
2803      *
2804      * @param array  the array to traverse for looking for the object, may be {@code null}
2805      * @param valueToFind  the value to find
2806      * @param startIndex  the start index to travers backwards from
2807      * @return the last index of the value within the array,
2808      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2809      */
2810     public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
2811         if (ArrayUtils.isEmpty(array)) {
2812             return INDEX_NOT_FOUND;
2813         }
2814         if (startIndex < 0) {
2815             return INDEX_NOT_FOUND;
2816         } else if (startIndex >= array.length) {
2817             startIndex = array.length - 1;
2818         }
2819         for (int i = startIndex; i >= 0; i--) {
2820             if (valueToFind == array[i]) {
2821                 return i;
2822             }
2823         }
2824         return INDEX_NOT_FOUND;
2825     }
2826 
2827     /**
2828      * <p>Checks if the value is in the given array.</p>
2829      *
2830      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2831      *
2832      * @param array  the array to search through
2833      * @param valueToFind  the value to find
2834      * @return {@code true} if the array contains the object
2835      */
2836     public static boolean contains(final float[] array, final float valueToFind) {
2837         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2838     }
2839 
2840     // boolean IndexOf
2841     //-----------------------------------------------------------------------
2842     /**
2843      * <p>Finds the index of the given value in the array.</p>
2844      *
2845      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2846      *
2847      * @param array  the array to search through for the object, may be {@code null}
2848      * @param valueToFind  the value to find
2849      * @return the index of the value within the array,
2850      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2851      */
2852     public static int indexOf(final boolean[] array, final boolean valueToFind) {
2853         return indexOf(array, valueToFind, 0);
2854     }
2855 
2856     /**
2857      * <p>Finds the index of the given value in the array starting at the given index.</p>
2858      *
2859      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2860      *
2861      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2862      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2863      *
2864      * @param array  the array to search through for the object, may be {@code null}
2865      * @param valueToFind  the value to find
2866      * @param startIndex  the index to start searching at
2867      * @return the index of the value within the array,
2868      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null}
2869      *  array input
2870      */
2871     public static int indexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
2872         if (ArrayUtils.isEmpty(array)) {
2873             return INDEX_NOT_FOUND;
2874         }
2875         if (startIndex < 0) {
2876             startIndex = 0;
2877         }
2878         for (int i = startIndex; i < array.length; i++) {
2879             if (valueToFind == array[i]) {
2880                 return i;
2881             }
2882         }
2883         return INDEX_NOT_FOUND;
2884     }
2885 
2886     /**
2887      * <p>Finds the last index of the given value within the array.</p>
2888      *
2889      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if
2890      * {@code null} array input.</p>
2891      *
2892      * @param array  the array to travers backwords looking for the object, may be {@code null}
2893      * @param valueToFind  the object to find
2894      * @return the last index of the value within the array,
2895      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2896      */
2897     public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
2898         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2899     }
2900 
2901     /**
2902      * <p>Finds the last index of the given value in the array starting at the given index.</p>
2903      *
2904      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2905      *
2906      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
2907      * the array length will search from the end of the array.</p>
2908      *
2909      * @param array  the array to traverse for looking for the object, may be {@code null}
2910      * @param valueToFind  the value to find
2911      * @param startIndex  the start index to travers backwards from
2912      * @return the last index of the value within the array,
2913      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2914      */
2915     public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
2916         if (ArrayUtils.isEmpty(array)) {
2917             return INDEX_NOT_FOUND;
2918         }
2919         if (startIndex < 0) {
2920             return INDEX_NOT_FOUND;
2921         } else if (startIndex >= array.length) {
2922             startIndex = array.length - 1;
2923         }
2924         for (int i = startIndex; i >= 0; i--) {
2925             if (valueToFind == array[i]) {
2926                 return i;
2927             }
2928         }
2929         return INDEX_NOT_FOUND;
2930     }
2931 
2932     /**
2933      * <p>Checks if the value is in the given array.</p>
2934      *
2935      * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2936      *
2937      * @param array  the array to search through
2938      * @param valueToFind  the value to find
2939      * @return {@code true} if the array contains the object
2940      */
2941     public static boolean contains(final boolean[] array, final boolean valueToFind) {
2942         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2943     }
2944 
2945     // Primitive/Object array converters
2946     // ----------------------------------------------------------------------
2947 
2948     // Character array converters
2949     // ----------------------------------------------------------------------
2950     /**
2951      * <p>Converts an array of object Characters to primitives.</p>
2952      *
2953      * <p>This method returns {@code null} for a {@code null} input array.</p>
2954      *
2955      * @param array  a {@code Character} array, may be {@code null}
2956      * @return a {@code char} array, {@code null} if null array input
2957      * @throws NullPointerException if array content is {@code null}
2958      */
2959     public static char[] toPrimitive(final Character[] array) {
2960         if (array == null) {
2961             return null;
2962         } else if (array.length == 0) {
2963             return EMPTY_CHAR_ARRAY;
2964         }
2965         final char[] result = new char[array.length];
2966         for (int i = 0; i < array.length; i++) {
2967             result[i] = array[i].charValue();
2968         }
2969         return result;
2970     }
2971 
2972     /**
2973      * <p>Converts an array of object Character to primitives handling {@code null}.</p>
2974      *
2975      * <p>This method returns {@code null} for a {@code null} input array.</p>
2976      *
2977      * @param array  a {@code Character} array, may be {@code null}
2978      * @param valueForNull  the value to insert if {@code null} found
2979      * @return a {@code char} array, {@code null} if null array input
2980      */
2981     public static char[] toPrimitive(final Character[] array, final char valueForNull) {
2982         if (array == null) {
2983             return null;
2984         } else if (array.length == 0) {
2985             return EMPTY_CHAR_ARRAY;
2986         }
2987         final char[] result = new char[array.length];
2988         for (int i = 0; i < array.length; i++) {
2989             final Character b = array[i];
2990             result[i] = (b == null ? valueForNull : b.charValue());
2991         }
2992         return result;
2993     }
2994 
2995     /**
2996      * <p>Converts an array of primitive chars to objects.</p>
2997      *
2998      * <p>This method returns {@code null} for a {@code null} input array.</p>
2999      *
3000      * @param array a {@code char} array
3001      * @return a {@code Character} array, {@code null} if null array input
3002      */
3003     public static Character[] toObject(final char[] array) {
3004         if (array == null) {
3005             return null;
3006         } else if (array.length == 0) {
3007             return EMPTY_CHARACTER_OBJECT_ARRAY;
3008         }
3009         final Character[] result = new Character[array.length];
3010         for (int i = 0; i < array.length; i++) {
3011             result[i] = Character.valueOf(array[i]);
3012         }
3013         return result;
3014      }
3015 
3016     // Long array converters
3017     // ----------------------------------------------------------------------
3018     /**
3019      * <p>Converts an array of object Longs to primitives.</p>
3020      *
3021      * <p>This method returns {@code null} for a {@code null} input array.</p>
3022      *
3023      * @param array  a {@code Long} array, may be {@code null}
3024      * @return a {@code long} array, {@code null} if null array input
3025      * @throws NullPointerException if array content is {@code null}
3026      */
3027     public static long[] toPrimitive(final Long[] array) {
3028         if (array == null) {
3029             return null;
3030         } else if (array.length == 0) {
3031             return EMPTY_LONG_ARRAY;
3032         }
3033         final long[] result = new long[array.length];
3034         for (int i = 0; i < array.length; i++) {
3035             result[i] = array[i].longValue();
3036         }
3037         return result;
3038     }
3039 
3040     /**
3041      * <p>Converts an array of object Long to primitives handling {@code null}.</p>
3042      *
3043      * <p>This method returns {@code null} for a {@code null} input array.</p>
3044      *
3045      * @param array  a {@code Long} array, may be {@code null}
3046      * @param valueForNull  the value to insert if {@code null} found
3047      * @return a {@code long} array, {@code null} if null array input
3048      */
3049     public static long[] toPrimitive(final Long[] array, final long valueForNull) {
3050         if (array == null) {
3051             return null;
3052         } else if (array.length == 0) {
3053             return EMPTY_LONG_ARRAY;
3054         }
3055         final long[] result = new long[array.length];
3056         for (int i = 0; i < array.length; i++) {
3057             final Long b = array[i];
3058             result[i] = (b == null ? valueForNull : b.longValue());
3059         }
3060         return result;
3061     }
3062 
3063     /**
3064      * <p>Converts an array of primitive longs to objects.</p>
3065      *
3066      * <p>This method returns {@code null} for a {@code null} input array.</p>
3067      *
3068      * @param array  a {@code long} array
3069      * @return a {@code Long} array, {@code null} if null array input
3070      */
3071     public static Long[] toObject(final long[] array) {
3072         if (array == null) {
3073             return null;
3074         } else if (array.length == 0) {
3075             return EMPTY_LONG_OBJECT_ARRAY;
3076         }
3077         final Long[] result = new Long[array.length];
3078         for (int i = 0; i < array.length; i++) {
3079             result[i] = Long.valueOf(array[i]);
3080         }
3081         return result;
3082     }
3083 
3084     // Int array converters
3085     // ----------------------------------------------------------------------
3086     /**
3087      * <p>Converts an array of object Integers to primitives.</p>
3088      *
3089      * <p>This method returns {@code null} for a {@code null} input array.</p>
3090      *
3091      * @param array  a {@code Integer} array, may be {@code null}
3092      * @return an {@code int} array, {@code null} if null array input
3093      * @throws NullPointerException if array content is {@code null}
3094      */
3095     public static int[] toPrimitive(final Integer[] array) {
3096         if (array == null) {
3097             return null;
3098         } else if (array.length == 0) {
3099             return EMPTY_INT_ARRAY;
3100         }
3101         final int[] result = new int[array.length];
3102         for (int i = 0; i < array.length; i++) {
3103             result[i] = array[i].intValue();
3104         }
3105         return result;
3106     }
3107 
3108     /**
3109      * <p>Converts an array of object Integer to primitives handling {@code null}.</p>
3110      *
3111      * <p>This method returns {@code null} for a {@code null} input array.</p>
3112      *
3113      * @param array  a {@code Integer} array, may be {@code null}
3114      * @param valueForNull  the value to insert if {@code null} found
3115      * @return an {@code int} array, {@code null} if null array input
3116      */
3117     public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
3118         if (array == null) {
3119             return null;
3120         } else if (array.length == 0) {
3121             return EMPTY_INT_ARRAY;
3122         }
3123         final int[] result = new int[array.length];
3124         for (int i = 0; i < array.length; i++) {
3125             final Integer b = array[i];
3126             result[i] = (b == null ? valueForNull : b.intValue());
3127         }
3128         return result;
3129     }
3130 
3131     /**
3132      * <p>Converts an array of primitive ints to objects.</p>
3133      *
3134      * <p>This method returns {@code null} for a {@code null} input array.</p>
3135      *
3136      * @param array  an {@code int} array
3137      * @return an {@code Integer} array, {@code null} if null array input
3138      */
3139     public static Integer[] toObject(final int[] array) {
3140         if (array == null) {
3141             return null;
3142         } else if (array.length == 0) {
3143             return EMPTY_INTEGER_OBJECT_ARRAY;
3144         }
3145         final Integer[] result = new Integer[array.length];
3146         for (int i = 0; i < array.length; i++) {
3147             result[i] = Integer.valueOf(array[i]);
3148         }
3149         return result;
3150     }
3151 
3152     // Short array converters
3153     // ----------------------------------------------------------------------
3154     /**
3155      * <p>Converts an array of object Shorts to primitives.</p>
3156      *
3157      * <p>This method returns {@code null} for a {@code null} input array.</p>
3158      *
3159      * @param array  a {@code Short} array, may be {@code null}
3160      * @return a {@code byte} array, {@code null} if null array input
3161      * @throws NullPointerException if array content is {@code null}
3162      */
3163     public static short[] toPrimitive(final Short[] array) {
3164         if (array == null) {
3165             return null;
3166         } else if (array.length == 0) {
3167             return EMPTY_SHORT_ARRAY;
3168         }
3169         final short[] result = new short[array.length];
3170         for (int i = 0; i < array.length; i++) {
3171             result[i] = array[i].shortValue();
3172         }
3173         return result;
3174     }
3175 
3176     /**
3177      * <p>Converts an array of object Short to primitives handling {@code null}.</p>
3178      *
3179      * <p>This method returns {@code null} for a {@code null} input array.</p>
3180      *
3181      * @param array  a {@code Short} array, may be {@code null}
3182      * @param valueForNull  the value to insert if {@code null} found
3183      * @return a {@code byte} array, {@code null} if null array input
3184      */
3185     public static short[] toPrimitive(final Short[] array, final short valueForNull) {
3186         if (array == null) {
3187             return null;
3188         } else if (array.length == 0) {
3189             return EMPTY_SHORT_ARRAY;
3190         }
3191         final short[] result = new short[array.length];
3192         for (int i = 0; i < array.length; i++) {
3193             final Short b = array[i];
3194             result[i] = (b == null ? valueForNull : b.shortValue());
3195         }
3196         return result;
3197     }
3198 
3199     /**
3200      * <p>Converts an array of primitive shorts to objects.</p>
3201      *
3202      * <p>This method returns {@code null} for a {@code null} input array.</p>
3203      *
3204      * @param array  a {@code short} array
3205      * @return a {@code Short} array, {@code null} if null array input
3206      */
3207     public static Short[] toObject(final short[] array) {
3208         if (array == null) {
3209             return null;
3210         } else if (array.length == 0) {
3211             return EMPTY_SHORT_OBJECT_ARRAY;
3212         }
3213         final Short[] result = new Short[array.length];
3214         for (int i = 0; i < array.length; i++) {
3215             result[i] = Short.valueOf(array[i]);
3216         }
3217         return result;
3218     }
3219 
3220     // Byte array converters
3221     // ----------------------------------------------------------------------
3222     /**
3223      * <p>Converts an array of object Bytes to primitives.</p>
3224      *
3225      * <p>This method returns {@code null} for a {@code null} input array.</p>
3226      *
3227      * @param array  a {@code Byte} array, may be {@code null}
3228      * @return a {@code byte} array, {@code null} if null array input
3229      * @throws NullPointerException if array content is {@code null}
3230      */
3231     public static byte[] toPrimitive(final Byte[] array) {
3232         if (array == null) {
3233             return null;
3234         } else if (array.length == 0) {
3235             return EMPTY_BYTE_ARRAY;
3236         }
3237         final byte[] result = new byte[array.length];
3238         for (int i = 0; i < array.length; i++) {
3239             result[i] = array[i].byteValue();
3240         }
3241         return result;
3242     }
3243 
3244     /**
3245      * <p>Converts an array of object Bytes to primitives handling {@code null}.</p>
3246      *
3247      * <p>This method returns {@code null} for a {@code null} input array.</p>
3248      *
3249      * @param array  a {@code Byte} array, may be {@code null}
3250      * @param valueForNull  the value to insert if {@code null} found
3251      * @return a {@code byte} array, {@code null} if null array input
3252      */
3253     public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
3254         if (array == null) {
3255             return null;
3256         } else if (array.length == 0) {
3257             return EMPTY_BYTE_ARRAY;
3258         }
3259         final byte[] result = new byte[array.length];
3260         for (int i = 0; i < array.length; i++) {
3261             final Byte b = array[i];
3262             result[i] = (b == null ? valueForNull : b.byteValue());
3263         }
3264         return result;
3265     }
3266 
3267     /**
3268      * <p>Converts an array of primitive bytes to objects.</p>
3269      *
3270      * <p>This method returns {@code null} for a {@code null} input array.</p>
3271      *
3272      * @param array  a {@code byte} array
3273      * @return a {@code Byte} array, {@code null} if null array input
3274      */
3275     public static Byte[] toObject(final byte[] array) {
3276         if (array == null) {
3277             return null;
3278         } else if (array.length == 0) {
3279             return EMPTY_BYTE_OBJECT_ARRAY;
3280         }
3281         final Byte[] result = new Byte[array.length];
3282         for (int i = 0; i < array.length; i++) {
3283             result[i] = Byte.valueOf(array[i]);
3284         }
3285         return result;
3286     }
3287 
3288     // Double array converters
3289     // ----------------------------------------------------------------------
3290     /**
3291      * <p>Converts an array of object Doubles to primitives.</p>
3292      *
3293      * <p>This method returns {@code null} for a {@code null} input array.</p>
3294      *
3295      * @param array  a {@code Double} array, may be {@code null}
3296      * @return a {@code double} array, {@code null} if null array input
3297      * @throws NullPointerException if array content is {@code null}
3298      */
3299     public static double[] toPrimitive(final Double[] array) {
3300         if (array == null) {
3301             return null;
3302         } else if (array.length == 0) {
3303             return EMPTY_DOUBLE_ARRAY;
3304         }
3305         final double[] result = new double[array.length];
3306         for (int i = 0; i < array.length; i++) {
3307             result[i] = array[i].doubleValue();
3308         }
3309         return result;
3310     }
3311 
3312     /**
3313      * <p>Converts an array of object Doubles to primitives handling {@code null}.</p>
3314      *
3315      * <p>This method returns {@code null} for a {@code null} input array.</p>
3316      *
3317      * @param array  a {@code Double} array, may be {@code null}
3318      * @param valueForNull  the value to insert if {@code null} found
3319      * @return a {@code double} array, {@code null} if null array input
3320      */
3321     public static double[] toPrimitive(final Double[] array, final double valueForNull) {
3322         if (array == null) {
3323             return null;
3324         } else if (array.length == 0) {
3325             return EMPTY_DOUBLE_ARRAY;
3326         }
3327         final double[] result = new double[array.length];
3328         for (int i = 0; i < array.length; i++) {
3329             final Double b = array[i];
3330             result[i] = (b == null ? valueForNull : b.doubleValue());
3331         }
3332         return result;
3333     }
3334 
3335     /**
3336      * <p>Converts an array of primitive doubles to objects.</p>
3337      *
3338      * <p>This method returns {@code null} for a {@code null} input array.</p>
3339      *
3340      * @param array  a {@code double} array
3341      * @return a {@code Double} array, {@code null} if null array input
3342      */
3343     public static Double[] toObject(final double[] array) {
3344         if (array == null) {
3345             return null;
3346         } else if (array.length == 0) {
3347             return EMPTY_DOUBLE_OBJECT_ARRAY;
3348         }
3349         final Double[] result = new Double[array.length];
3350         for (int i = 0; i < array.length; i++) {
3351             result[i] = Double.valueOf(array[i]);
3352         }
3353         return result;
3354     }
3355 
3356     //   Float array converters
3357     // ----------------------------------------------------------------------
3358     /**
3359      * <p>Converts an array of object Floats to primitives.</p>
3360      *
3361      * <p>This method returns {@code null} for a {@code null} input array.</p>
3362      *
3363      * @param array  a {@code Float} array, may be {@code null}
3364      * @return a {@code float} array, {@code null} if null array input
3365      * @throws NullPointerException if array content is {@code null}
3366      */
3367     public static float[] toPrimitive(final Float[] array) {
3368         if (array == null) {
3369             return null;
3370         } else if (array.length == 0) {
3371             return EMPTY_FLOAT_ARRAY;
3372         }
3373         final float[] result = new float[array.length];
3374         for (int i = 0; i < array.length; i++) {
3375             result[i] = array[i].floatValue();
3376         }
3377         return result;
3378     }
3379 
3380     /**
3381      * <p>Converts an array of object Floats to primitives handling {@code null}.</p>
3382      *
3383      * <p>This method returns {@code null} for a {@code null} input array.</p>
3384      *
3385      * @param array  a {@code Float} array, may be {@code null}
3386      * @param valueForNull  the value to insert if {@code null} found
3387      * @return a {@code float} array, {@code null} if null array input
3388      */
3389     public static float[] toPrimitive(final Float[] array, final float valueForNull) {
3390         if (array == null) {
3391             return null;
3392         } else if (array.length == 0) {
3393             return EMPTY_FLOAT_ARRAY;
3394         }
3395         final float[] result = new float[array.length];
3396         for (int i = 0; i < array.length; i++) {
3397             final Float b = array[i];
3398             result[i] = (b == null ? valueForNull : b.floatValue());
3399         }
3400         return result;
3401     }
3402 
3403     /**
3404      * <p>Converts an array of primitive floats to objects.</p>
3405      *
3406      * <p>This method returns {@code null} for a {@code null} input array.</p>
3407      *
3408      * @param array  a {@code float} array
3409      * @return a {@code Float} array, {@code null} if null array input
3410      */
3411     public static Float[] toObject(final float[] array) {
3412         if (array == null) {
3413             return null;
3414         } else if (array.length == 0) {
3415             return EMPTY_FLOAT_OBJECT_ARRAY;
3416         }
3417         final Float[] result = new Float[array.length];
3418         for (int i = 0; i < array.length; i++) {
3419             result[i] = Float.valueOf(array[i]);
3420         }
3421         return result;
3422     }
3423 
3424     // Boolean array converters
3425     // ----------------------------------------------------------------------
3426     /**
3427      * <p>Converts an array of object Booleans to primitives.</p>
3428      *
3429      * <p>This method returns {@code null} for a {@code null} input array.</p>
3430      *
3431      * @param array  a {@code Boolean} array, may be {@code null}
3432      * @return a {@code boolean} array, {@code null} if null array input
3433      * @throws NullPointerException if array content is {@code null}
3434      */
3435     public static boolean[] toPrimitive(final Boolean[] array) {
3436         if (array == null) {
3437             return null;
3438         } else if (array.length == 0) {
3439             return EMPTY_BOOLEAN_ARRAY;
3440         }
3441         final boolean[] result = new boolean[array.length];
3442         for (int i = 0; i < array.length; i++) {
3443             result[i] = array[i].booleanValue();
3444         }
3445         return result;
3446     }
3447 
3448     /**
3449      * <p>Converts an array of object Booleans to primitives handling {@code null}.</p>
3450      *
3451      * <p>This method returns {@code null} for a {@code null} input array.</p>
3452      *
3453      * @param array  a {@code Boolean} array, may be {@code null}
3454      * @param valueForNull  the value to insert if {@code null} found
3455      * @return a {@code boolean} array, {@code null} if null array input
3456      */
3457     public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
3458         if (array == null) {
3459             return null;
3460         } else if (array.length == 0) {
3461             return EMPTY_BOOLEAN_ARRAY;
3462         }
3463         final boolean[] result = new boolean[array.length];
3464         for (int i = 0; i < array.length; i++) {
3465             final Boolean b = array[i];
3466             result[i] = (b == null ? valueForNull : b.booleanValue());
3467         }
3468         return result;
3469     }
3470 
3471     /**
3472      * <p>Converts an array of primitive booleans to objects.</p>
3473      *
3474      * <p>This method returns {@code null} for a {@code null} input array.</p>
3475      *
3476      * @param array  a {@code boolean} array
3477      * @return a {@code Boolean} array, {@code null} if null array input
3478      */
3479     public static Boolean[] toObject(final boolean[] array) {
3480         if (array == null) {
3481             return null;
3482         } else if (array.length == 0) {
3483             return EMPTY_BOOLEAN_OBJECT_ARRAY;
3484         }
3485         final Boolean[] result = new Boolean[array.length];
3486         for (int i = 0; i < array.length; i++) {
3487             result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
3488         }
3489         return result;
3490     }
3491 
3492     // ----------------------------------------------------------------------
3493     /**
3494      * <p>Checks if an array of Objects is empty or {@code null}.</p>
3495      *
3496      * @param array  the array to test
3497      * @return {@code true} if the array is empty or {@code null}
3498      * @since 2.1
3499      */
3500     public static boolean isEmpty(final Object[] array) {
3501         return array == null || array.length == 0;
3502     }
3503 
3504     /**
3505      * <p>Checks if an array of primitive longs is empty or {@code null}.</p>
3506      *
3507      * @param array  the array to test
3508      * @return {@code true} if the array is empty or {@code null}
3509      * @since 2.1
3510      */
3511     public static boolean isEmpty(final long[] array) {
3512         return array == null || array.length == 0;
3513     }
3514 
3515     /**
3516      * <p>Checks if an array of primitive ints is empty or {@code null}.</p>
3517      *
3518      * @param array  the array to test
3519      * @return {@code true} if the array is empty or {@code null}
3520      * @since 2.1
3521      */
3522     public static boolean isEmpty(final int[] array) {
3523         return array == null || array.length == 0;
3524     }
3525 
3526     /**
3527      * <p>Checks if an array of primitive shorts is empty or {@code null}.</p>
3528      *
3529      * @param array  the array to test
3530      * @return {@code true} if the array is empty or {@code null}
3531      * @since 2.1
3532      */
3533     public static boolean isEmpty(final short[] array) {
3534         return array == null || array.length == 0;
3535     }
3536 
3537     /**
3538      * <p>Checks if an array of primitive chars is empty or {@code null}.</p>
3539      *
3540      * @param array  the array to test
3541      * @return {@code true} if the array is empty or {@code null}
3542      * @since 2.1
3543      */
3544     public static boolean isEmpty(final char[] array) {
3545         return array == null || array.length == 0;
3546     }
3547 
3548     /**
3549      * <p>Checks if an array of primitive bytes is empty or {@code null}.</p>
3550      *
3551      * @param array  the array to test
3552      * @return {@code true} if the array is empty or {@code null}
3553      * @since 2.1
3554      */
3555     public static boolean isEmpty(final byte[] array) {
3556         return array == null || array.length == 0;
3557     }
3558 
3559     /**
3560      * <p>Checks if an array of primitive doubles is empty or {@code null}.</p>
3561      *
3562      * @param array  the array to test
3563      * @return {@code true} if the array is empty or {@code null}
3564      * @since 2.1
3565      */
3566     public static boolean isEmpty(final double[] array) {
3567         return array == null || array.length == 0;
3568     }
3569 
3570     /**
3571      * <p>Checks if an array of primitive floats is empty or {@code null}.</p>
3572      *
3573      * @param array  the array to test
3574      * @return {@code true} if the array is empty or {@code null}
3575      * @since 2.1
3576      */
3577     public static boolean isEmpty(final float[] array) {
3578         return array == null || array.length == 0;
3579     }
3580 
3581     /**
3582      * <p>Checks if an array of primitive booleans is empty or {@code null}.</p>
3583      *
3584      * @param array  the array to test
3585      * @return {@code true} if the array is empty or {@code null}
3586      * @since 2.1
3587      */
3588     public static boolean isEmpty(final boolean[] array) {
3589         return array == null || array.length == 0;
3590     }
3591 
3592     // ----------------------------------------------------------------------
3593     /**
3594      * <p>Checks if an array of Objects is not empty or not {@code null}.</p>
3595      *
3596      * @param <T> the component type of the array
3597      * @param array  the array to test
3598      * @return {@code true} if the array is not empty or not {@code null}
3599      * @since 2.5
3600      */
3601      public static <T> boolean isNotEmpty(final T[] array) {
3602          return (array != null && array.length != 0);
3603      }
3604 
3605     /**
3606      * <p>Checks if an array of primitive longs is not empty or not {@code null}.</p>
3607      *
3608      * @param array  the array to test
3609      * @return {@code true} if the array is not empty or not {@code null}
3610      * @since 2.5
3611      */
3612     public static boolean isNotEmpty(final long[] array) {
3613         return (array != null && array.length != 0);
3614     }
3615 
3616     /**
3617      * <p>Checks if an array of primitive ints is not empty or not {@code null}.</p>
3618      *
3619      * @param array  the array to test
3620      * @return {@code true} if the array is not empty or not {@code null}
3621      * @since 2.5
3622      */
3623     public static boolean isNotEmpty(final int[] array) {
3624         return (array != null && array.length != 0);
3625     }
3626 
3627     /**
3628      * <p>Checks if an array of primitive shorts is not empty or not {@code null}.</p>
3629      *
3630      * @param array  the array to test
3631      * @return {@code true} if the array is not empty or not {@code null}
3632      * @since 2.5
3633      */
3634     public static boolean isNotEmpty(final short[] array) {
3635         return (array != null && array.length != 0);
3636     }
3637 
3638     /**
3639      * <p>Checks if an array of primitive chars is not empty or not {@code null}.</p>
3640      *
3641      * @param array  the array to test
3642      * @return {@code true} if the array is not empty or not {@code null}
3643      * @since 2.5
3644      */
3645     public static boolean isNotEmpty(final char[] array) {
3646         return (array != null && array.length != 0);
3647     }
3648 
3649     /**
3650      * <p>Checks if an array of primitive bytes is not empty or not {@code null}.</p>
3651      *
3652      * @param array  the array to test
3653      * @return {@code true} if the array is not empty or not {@code null}
3654      * @since 2.5
3655      */
3656     public static boolean isNotEmpty(final byte[] array) {
3657         return (array != null && array.length != 0);
3658     }
3659 
3660     /**
3661      * <p>Checks if an array of primitive doubles is not empty or not {@code null}.</p>
3662      *
3663      * @param array  the array to test
3664      * @return {@code true} if the array is not empty or not {@code null}
3665      * @since 2.5
3666      */
3667     public static boolean isNotEmpty(final double[] array) {
3668         return (array != null && array.length != 0);
3669     }
3670 
3671     /**
3672      * <p>Checks if an array of primitive floats is not empty or not {@code null}.</p>
3673      *
3674      * @param array  the array to test
3675      * @return {@code true} if the array is not empty or not {@code null}
3676      * @since 2.5
3677      */
3678     public static boolean isNotEmpty(final float[] array) {
3679         return (array != null && array.length != 0);
3680     }
3681 
3682     /**
3683      * <p>Checks if an array of primitive booleans is not empty or not {@code null}.</p>
3684      *
3685      * @param array  the array to test
3686      * @return {@code true} if the array is not empty or not {@code null}
3687      * @since 2.5
3688      */
3689     public static boolean isNotEmpty(final boolean[] array) {
3690         return (array != null && array.length != 0);
3691     }
3692 
3693     /**
3694      * <p>Adds all the elements of the given arrays into a new array.</p>
3695      * <p>The new array contains all of the element of {@code array1} followed
3696      * by all of the elements {@code array2}. When an array is returned, it is always
3697      * a new array.</p>
3698      *
3699      * <pre>
3700      * ArrayUtils.addAll(null, null)     = null
3701      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3702      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3703      * ArrayUtils.addAll([], [])         = []
3704      * ArrayUtils.addAll([null], [null]) = [null, null]
3705      * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
3706      * </pre>
3707      *
3708      * @param <T> the component type of the array
3709      * @param array1  the first array whose elements are added to the new array, may be {@code null}
3710      * @param array2  the second array whose elements are added to the new array, may be {@code null}
3711      * @return The new array, {@code null} if both arrays are {@code null}.
3712      *      The type of the new array is the type of the first array,
3713      *      unless the first array is null, in which case the type is the same as the second array.
3714      * @since 2.1
3715      * @throws IllegalArgumentException if the array types are incompatible
3716      */
3717     public static <T> T[] addAll(final T[] array1, final T... array2) {
3718         if (array1 == null) {
3719             return clone(array2);
3720         } else if (array2 == null) {
3721             return clone(array1);
3722         }
3723         final Class<?> type1 = array1.getClass().getComponentType();
3724         @SuppressWarnings("unchecked") // OK, because array is of type T
3725         final
3726         T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
3727         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3728         try {
3729             System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3730         } catch (final ArrayStoreException ase) {
3731             // Check if problem was due to incompatible types
3732             /*
3733              * We do this here, rather than before the copy because:
3734              * - it would be a wasted check most of the time
3735              * - safer, in case check turns out to be too strict
3736              */
3737             final Class<?> type2 = array2.getClass().getComponentType();
3738             if (!type1.isAssignableFrom(type2)){
3739                 throw new IllegalArgumentException("Cannot store "+type2.getName()+" in an array of "
3740                         +type1.getName(), ase);
3741             }
3742             throw ase; // No, so rethrow original
3743         }
3744         return joinedArray;
3745     }
3746 
3747     /**
3748      * <p>Adds all the elements of the given arrays into a new array.</p>
3749      * <p>The new array contains all of the element of {@code array1} followed
3750      * by all of the elements {@code array2}. When an array is returned, it is always
3751      * a new array.</p>
3752      *
3753      * <pre>
3754      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3755      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3756      * ArrayUtils.addAll([], [])         = []
3757      * </pre>
3758      *
3759      * @param array1  the first array whose elements are added to the new array.
3760      * @param array2  the second array whose elements are added to the new array.
3761      * @return The new boolean[] array.
3762      * @since 2.1
3763      */
3764     public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
3765         if (array1 == null) {
3766             return clone(array2);
3767         } else if (array2 == null) {
3768             return clone(array1);
3769         }
3770         final boolean[] joinedArray = new boolean[array1.length + array2.length];
3771         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3772         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3773         return joinedArray;
3774     }
3775 
3776     /**
3777      * <p>Adds all the elements of the given arrays into a new array.</p>
3778      * <p>The new array contains all of the element of {@code array1} followed
3779      * by all of the elements {@code array2}. When an array is returned, it is always
3780      * a new array.</p>
3781      *
3782      * <pre>
3783      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3784      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3785      * ArrayUtils.addAll([], [])         = []
3786      * </pre>
3787      *
3788      * @param array1  the first array whose elements are added to the new array.
3789      * @param array2  the second array whose elements are added to the new array.
3790      * @return The new char[] array.
3791      * @since 2.1
3792      */
3793     public static char[] addAll(final char[] array1, final char... array2) {
3794         if (array1 == null) {
3795             return clone(array2);
3796         } else if (array2 == null) {
3797             return clone(array1);
3798         }
3799         final char[] joinedArray = new char[array1.length + array2.length];
3800         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3801         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3802         return joinedArray;
3803     }
3804 
3805     /**
3806      * <p>Adds all the elements of the given arrays into a new array.</p>
3807      * <p>The new array contains all of the element of {@code array1} followed
3808      * by all of the elements {@code array2}. When an array is returned, it is always
3809      * a new array.</p>
3810      *
3811      * <pre>
3812      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3813      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3814      * ArrayUtils.addAll([], [])         = []
3815      * </pre>
3816      *
3817      * @param array1  the first array whose elements are added to the new array.
3818      * @param array2  the second array whose elements are added to the new array.
3819      * @return The new byte[] array.
3820      * @since 2.1
3821      */
3822     public static byte[] addAll(final byte[] array1, final byte... array2) {
3823         if (array1 == null) {
3824             return clone(array2);
3825         } else if (array2 == null) {
3826             return clone(array1);
3827         }
3828         final byte[] joinedArray = new byte[array1.length + array2.length];
3829         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3830         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3831         return joinedArray;
3832     }
3833 
3834     /**
3835      * <p>Adds all the elements of the given arrays into a new array.</p>
3836      * <p>The new array contains all of the element of {@code array1} followed
3837      * by all of the elements {@code array2}. When an array is returned, it is always
3838      * a new array.</p>
3839      *
3840      * <pre>
3841      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3842      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3843      * ArrayUtils.addAll([], [])         = []
3844      * </pre>
3845      *
3846      * @param array1  the first array whose elements are added to the new array.
3847      * @param array2  the second array whose elements are added to the new array.
3848      * @return The new short[] array.
3849      * @since 2.1
3850      */
3851     public static short[] addAll(final short[] array1, final short... array2) {
3852         if (array1 == null) {
3853             return clone(array2);
3854         } else if (array2 == null) {
3855             return clone(array1);
3856         }
3857         final short[] joinedArray = new short[array1.length + array2.length];
3858         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3859         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3860         return joinedArray;
3861     }
3862 
3863     /**
3864      * <p>Adds all the elements of the given arrays into a new array.</p>
3865      * <p>The new array contains all of the element of {@code array1} followed
3866      * by all of the elements {@code array2}. When an array is returned, it is always
3867      * a new array.</p>
3868      *
3869      * <pre>
3870      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3871      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3872      * ArrayUtils.addAll([], [])         = []
3873      * </pre>
3874      *
3875      * @param array1  the first array whose elements are added to the new array.
3876      * @param array2  the second array whose elements are added to the new array.
3877      * @return The new int[] array.
3878      * @since 2.1
3879      */
3880     public static int[] addAll(final int[] array1, final int... array2) {
3881         if (array1 == null) {
3882             return clone(array2);
3883         } else if (array2 == null) {
3884             return clone(array1);
3885         }
3886         final int[] joinedArray = new int[array1.length + array2.length];
3887         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3888         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3889         return joinedArray;
3890     }
3891 
3892     /**
3893      * <p>Adds all the elements of the given arrays into a new array.</p>
3894      * <p>The new array contains all of the element of {@code array1} followed
3895      * by all of the elements {@code array2}. When an array is returned, it is always
3896      * a new array.</p>
3897      *
3898      * <pre>
3899      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3900      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3901      * ArrayUtils.addAll([], [])         = []
3902      * </pre>
3903      *
3904      * @param array1  the first array whose elements are added to the new array.
3905      * @param array2  the second array whose elements are added to the new array.
3906      * @return The new long[] array.
3907      * @since 2.1
3908      */
3909     public static long[] addAll(final long[] array1, final long... array2) {
3910         if (array1 == null) {
3911             return clone(array2);
3912         } else if (array2 == null) {
3913             return clone(array1);
3914         }
3915         final long[] joinedArray = new long[array1.length + array2.length];
3916         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3917         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3918         return joinedArray;
3919     }
3920 
3921     /**
3922      * <p>Adds all the elements of the given arrays into a new array.</p>
3923      * <p>The new array contains all of the element of {@code array1} followed
3924      * by all of the elements {@code array2}. When an array is returned, it is always
3925      * a new array.</p>
3926      *
3927      * <pre>
3928      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3929      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3930      * ArrayUtils.addAll([], [])         = []
3931      * </pre>
3932      *
3933      * @param array1  the first array whose elements are added to the new array.
3934      * @param array2  the second array whose elements are added to the new array.
3935      * @return The new float[] array.
3936      * @since 2.1
3937      */
3938     public static float[] addAll(final float[] array1, final float... array2) {
3939         if (array1 == null) {
3940             return clone(array2);
3941         } else if (array2 == null) {
3942             return clone(array1);
3943         }
3944         final float[] joinedArray = new float[array1.length + array2.length];
3945         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3946         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3947         return joinedArray;
3948     }
3949 
3950     /**
3951      * <p>Adds all the elements of the given arrays into a new array.</p>
3952      * <p>The new array contains all of the element of {@code array1} followed
3953      * by all of the elements {@code array2}. When an array is returned, it is always
3954      * a new array.</p>
3955      *
3956      * <pre>
3957      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3958      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3959      * ArrayUtils.addAll([], [])         = []
3960      * </pre>
3961      *
3962      * @param array1  the first array whose elements are added to the new array.
3963      * @param array2  the second array whose elements are added to the new array.
3964      * @return The new double[] array.
3965      * @since 2.1
3966      */
3967     public static double[] addAll(final double[] array1, final double... array2) {
3968         if (array1 == null) {
3969             return clone(array2);
3970         } else if (array2 == null) {
3971             return clone(array1);
3972         }
3973         final double[] joinedArray = new double[array1.length + array2.length];
3974         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3975         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3976         return joinedArray;
3977     }
3978 
3979     /**
3980      * <p>Copies the given array and adds the given element at the end of the new array.</p>
3981      *
3982      * <p>The new array contains the same elements of the input
3983      * array plus the given element in the last position. The component type of
3984      * the new array is the same as that of the input array.</p>
3985      *
3986      * <p>If the input array is {@code null}, a new one element array is returned
3987      *  whose component type is the same as the element, unless the element itself is null,
3988      *  in which case the return type is Object[]</p>
3989      *
3990      * <pre>
3991      * ArrayUtils.add(null, null)      = [null]
3992      * ArrayUtils.add(null, "a")       = ["a"]
3993      * ArrayUtils.add(["a"], null)     = ["a", null]
3994      * ArrayUtils.add(["a"], "b")      = ["a", "b"]
3995      * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
3996      * </pre>
3997      *
3998      * @param <T> the component type of the array
3999      * @param array  the array to "add" the element to, may be {@code null}
4000      * @param element  the object to add, may be {@code null}
4001      * @return A new array containing the existing elements plus the new element
4002      * The returned array type will be that of the input array (unless null),
4003      * in which case it will have the same type as the element.
4004      * If both are null, an IllegalArgumentException is thrown
4005      * @since 2.1
4006      * @throws IllegalArgumentException if both arguments are null
4007      */
4008     public static <T> T[] add(final T[] array, final T element) {
4009         Class<?> type;
4010         if (array != null){
4011             type = array.getClass().getComponentType();
4012         } else if (element != null) {
4013             type = element.getClass();
4014         } else {
4015             throw new IllegalArgumentException("Arguments cannot both be null");
4016         }
4017         @SuppressWarnings("unchecked") // type must be T
4018         final
4019         T[] newArray = (T[]) copyArrayGrow1(array, type);
4020         newArray[newArray.length - 1] = element;
4021         return newArray;
4022     }
4023 
4024     /**
4025      * <p>Copies the given array and adds the given element at the end of the new array.</p>
4026      *
4027      * <p>The new array contains the same elements of the input
4028      * array plus the given element in the last position. The component type of
4029      * the new array is the same as that of the input array.</p>
4030      *
4031      * <p>If the input array is {@code null}, a new one element array is returned
4032      *  whose component type is the same as the element.</p>
4033      *
4034      * <pre>
4035      * ArrayUtils.add(null, true)          = [true]
4036      * ArrayUtils.add([true], false)       = [true, false]
4037      * ArrayUtils.add([true, false], true) = [true, false, true]
4038      * </pre>
4039      *
4040      * @param array  the array to copy and add the element to, may be {@code null}
4041      * @param element  the object to add at the last index of the new array
4042      * @return A new array containing the existing elements plus the new element
4043      * @since 2.1
4044      */
4045     public static boolean[] add(final boolean[] array, final boolean element) {
4046         final boolean[] newArray = (boolean[])copyArrayGrow1(array, Boolean.TYPE);
4047         newArray[newArray.length - 1] = element;
4048         return newArray;
4049     }
4050 
4051     /**
4052      * <p>Copies the given array and adds the given element at the end of the new array.</p>
4053      *
4054      * <p>The new array contains the same elements of the input
4055      * array plus the given element in the last position. The component type of
4056      * the new array is the same as that of the input array.</p>
4057      *
4058      * <p>If the input array is {@code null}, a new one element array is returned
4059      *  whose component type is the same as the element.</p>
4060      *
4061      * <pre>
4062      * ArrayUtils.add(null, 0)   = [0]
4063      * ArrayUtils.add([1], 0)    = [1, 0]
4064      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
4065      * </pre>
4066      *
4067      * @param array  the array to copy and add the element to, may be {@code null}
4068      * @param element  the object to add at the last index of the new array
4069      * @return A new array containing the existing elements plus the new element
4070      * @since 2.1
4071      */
4072     public static byte[] add(final byte[] array, final byte element) {
4073         final byte[] newArray = (byte[])copyArrayGrow1(array, Byte.TYPE);
4074         newArray[newArray.length - 1] = element;
4075         return newArray;
4076     }
4077 
4078     /**
4079      * <p>Copies the given array and adds the given element at the end of the new array.</p>
4080      *
4081      * <p>The new array contains the same elements of the input
4082      * array plus the given element in the last position. The component type of
4083      * the new array is the same as that of the input array.</p>
4084      *
4085      * <p>If the input array is {@code null}, a new one element array is returned
4086      *  whose component type is the same as the element.</p>
4087      *
4088      * <pre>
4089      * ArrayUtils.add(null, '0')       = ['0']
4090      * ArrayUtils.add(['1'], '0')      = ['1', '0']
4091      * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
4092      * </pre>
4093      *
4094      * @param array  the array to copy and add the element to, may be {@code null}
4095      * @param element  the object to add at the last index of the new array
4096      * @return A new array containing the existing elements plus the new element
4097      * @since 2.1
4098      */
4099     public static char[] add(final char[] array, final char element) {
4100         final char[] newArray = (char[])copyArrayGrow1(array, Character.TYPE);
4101         newArray[newArray.length - 1] = element;
4102         return newArray;
4103     }
4104 
4105     /**
4106      * <p>Copies the given array and adds the given element at the end of the new array.</p>
4107      *
4108      * <p>The new array contains the same elements of the input
4109      * array plus the given element in the last position. The component type of
4110      * the new array is the same as that of the input array.</p>
4111      *
4112      * <p>If the input array is {@code null}, a new one element array is returned
4113      *  whose component type is the same as the element.</p>
4114      *
4115      * <pre>
4116      * ArrayUtils.add(null, 0)   = [0]
4117      * ArrayUtils.add([1], 0)    = [1, 0]
4118      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
4119      * </pre>
4120      *
4121      * @param array  the array to copy and add the element to, may be {@code null}
4122      * @param element  the object to add at the last index of the new array
4123      * @return A new array containing the existing elements plus the new element
4124      * @since 2.1
4125      */
4126     public static double[] add(final double[] array, final double element) {
4127         final double[] newArray = (double[])copyArrayGrow1(array, Double.TYPE);
4128         newArray[newArray.length - 1] = element;
4129         return newArray;
4130     }
4131 
4132     /**
4133      * <p>Copies the given array and adds the given element at the end of the new array.</p>
4134      *
4135      * <p>The new array contains the same elements of the input
4136      * array plus the given element in the last position. The component type of
4137      * the new array is the same as that of the input array.</p>
4138      *
4139      * <p>If the input array is {@code null}, a new one element array is returned
4140      *  whose component type is the same as the element.</p>
4141      *
4142      * <pre>
4143      * ArrayUtils.add(null, 0)   = [0]
4144      * ArrayUtils.add([1], 0)    = [1, 0]
4145      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
4146      * </pre>
4147      *
4148      * @param array  the array to copy and add the element to, may be {@code null}
4149      * @param element  the object to add at the last index of the new array
4150      * @return A new array containing the existing elements plus the new element
4151      * @since 2.1
4152      */
4153     public static float[] add(final float[] array, final float element) {
4154         final float[] newArray = (float[])copyArrayGrow1(array, Float.TYPE);
4155         newArray[newArray.length - 1] = element;
4156         return newArray;
4157     }
4158 
4159     /**
4160      * <p>Copies the given array and adds the given element at the end of the new array.</p>
4161      *
4162      * <p>The new array contains the same elements of the input
4163      * array plus the given element in the last position. The component type of
4164      * the new array is the same as that of the input array.</p>
4165      *
4166      * <p>If the input array is {@code null}, a new one element array is returned
4167      *  whose component type is the same as the element.</p>
4168      *
4169      * <pre>
4170      * ArrayUtils.add(null, 0)   = [0]
4171      * ArrayUtils.add([1], 0)    = [1, 0]
4172      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
4173      * </pre>
4174      *
4175      * @param array  the array to copy and add the element to, may be {@code null}
4176      * @param element  the object to add at the last index of the new array
4177      * @return A new array containing the existing elements plus the new element
4178      * @since 2.1
4179      */
4180     public static int[] add(final int[] array, final int element) {
4181         final int[] newArray = (int[])copyArrayGrow1(array, Integer.TYPE);
4182         newArray[newArray.length - 1] = element;
4183         return newArray;
4184     }
4185 
4186     /**
4187      * <p>Copies the given array and adds the given element at the end of the new array.</p>
4188      *
4189      * <p>The new array contains the same elements of the input
4190      * array plus the given element in the last position. The component type of
4191      * the new array is the same as that of the input array.</p>
4192      *
4193      * <p>If the input array is {@code null}, a new one element array is returned
4194      *  whose component type is the same as the element.</p>
4195      *
4196      * <pre>
4197      * ArrayUtils.add(null, 0)   = [0]
4198      * ArrayUtils.add([1], 0)    = [1, 0]
4199      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
4200      * </pre>
4201      *
4202      * @param array  the array to copy and add the element to, may be {@code null}
4203      * @param element  the object to add at the last index of the new array
4204      * @return A new array containing the existing elements plus the new element
4205      * @since 2.1
4206      */
4207     public static long[] add(final long[] array, final long element) {
4208         final long[] newArray = (long[])copyArrayGrow1(array, Long.TYPE);
4209         newArray[newArray.length - 1] = element;
4210         return newArray;
4211     }
4212 
4213     /**
4214      * <p>Copies the given array and adds the given element at the end of the new array.</p>
4215      *
4216      * <p>The new array contains the same elements of the input
4217      * array plus the given element in the last position. The component type of
4218      * the new array is the same as that of the input array.</p>
4219      *
4220      * <p>If the input array is {@code null}, a new one element array is returned
4221      *  whose component type is the same as the element.</p>
4222      *
4223      * <pre>
4224      * ArrayUtils.add(null, 0)   = [0]
4225      * ArrayUtils.add([1], 0)    = [1, 0]
4226      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
4227      * </pre>
4228      *
4229      * @param array  the array to copy and add the element to, may be {@code null}
4230      * @param element  the object to add at the last index of the new array
4231      * @return A new array containing the existing elements plus the new element
4232      * @since 2.1
4233      */
4234     public static short[] add(final short[] array, final short element) {
4235         final short[] newArray = (short[])copyArrayGrow1(array, Short.TYPE);
4236         newArray[newArray.length - 1] = element;
4237         return newArray;
4238     }
4239 
4240     /**
4241      * Returns a copy of the given array of size 1 greater than the argument.
4242      * The last value of the array is left to the default value.
4243      *
4244      * @param array The array to copy, must not be {@code null}.
4245      * @param newArrayComponentType If {@code array} is {@code null}, create a
4246      * size 1 array of this type.
4247      * @return A new copy of the array of size 1 greater than the input.
4248      */
4249     private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {
4250         if (array != null) {
4251             final int arrayLength = Array.getLength(array);
4252             final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
4253             System.arraycopy(array, 0, newArray, 0, arrayLength);
4254             return newArray;
4255         }
4256         return Array.newInstance(newArrayComponentType, 1);
4257     }
4258 
4259     /**
4260      * <p>Inserts the specified element at the specified position in the array.
4261      * Shifts the element currently at that position (if any) and any subsequent
4262      * elements to the right (adds one to their indices).</p>
4263      *
4264      * <p>This method returns a new array with the same elements of the input
4265      * array plus the given element on the specified position. The component
4266      * type of the returned array is always the same as that of the input
4267      * array.</p>
4268      *
4269      * <p>If the input array is {@code null}, a new one element array is returned
4270      *  whose component type is the same as the element.</p>
4271      *
4272      * <pre>
4273      * ArrayUtils.add(null, 0, null)      = [null]
4274      * ArrayUtils.add(null, 0, "a")       = ["a"]
4275      * ArrayUtils.add(["a"], 1, null)     = ["a", null]
4276      * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
4277      * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
4278      * </pre>
4279      *
4280      * @param <T> the component type of the array
4281      * @param array  the array to add the element to, may be {@code null}
4282      * @param index  the position of the new object
4283      * @param element  the object to add
4284      * @return A new array containing the existing elements and the new element
4285      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
4286      * @throws IllegalArgumentException if both array and element are null
4287      */
4288     public static <T> T[] add(final T[] array, final int index, final T element) {
4289         Class<?> clss = null;
4290         if (array != null) {
4291             clss = array.getClass().getComponentType();
4292         } else if (element != null) {
4293             clss = element.getClass();
4294         } else {
4295             throw new IllegalArgumentException("Array and element cannot both be null");
4296         }
4297         @SuppressWarnings("unchecked") // the add method creates an array of type clss, which is type T
4298         final T[] newArray = (T[]) add(array, index, element, clss);
4299         return newArray;
4300     }
4301 
4302     /**
4303      * <p>Inserts the specified element at the specified position in the array.
4304      * Shifts the element currently at that position (if any) and any subsequent
4305      * elements to the right (adds one to their indices).</p>
4306      *
4307      * <p>This method returns a new array with the same elements of the input
4308      * array plus the given element on the specified position. The component
4309      * type of the returned array is always the same as that of the input
4310      * array.</p>
4311      *
4312      * <p>If the input array is {@code null}, a new one element array is returned
4313      *  whose component type is the same as the element.</p>
4314      *
4315      * <pre>
4316      * ArrayUtils.add(null, 0, true)          = [true]
4317      * ArrayUtils.add([true], 0, false)       = [false, true]
4318      * ArrayUtils.add([false], 1, true)       = [false, true]
4319      * ArrayUtils.add([true, false], 1, true) = [true, true, false]
4320      * </pre>
4321      *
4322      * @param array  the array to add the element to, may be {@code null}
4323      * @param index  the position of the new object
4324      * @param element  the object to add
4325      * @return A new array containing the existing elements and the new element
4326      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
4327      */
4328     public static boolean[] add(final boolean[] array, final int index, final boolean element) {
4329         return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
4330     }
4331 
4332     /**
4333      * <p>Inserts the specified element at the specified position in the array.
4334      * Shifts the element currently at that position (if any) and any subsequent
4335      * elements to the right (adds one to their indices).</p>
4336      *
4337      * <p>This method returns a new array with the same elements of the input
4338      * array plus the given element on the specified position. The component
4339      * type of the returned array is always the same as that of the input
4340      * array.</p>
4341      *
4342      * <p>If the input array is {@code null}, a new one element array is returned
4343      *  whose component type is the same as the element.</p>
4344      *
4345      * <pre>
4346      * ArrayUtils.add(null, 0, 'a')            = ['a']
4347      * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
4348      * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
4349      * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
4350      * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
4351      * </pre>
4352      *
4353      * @param array  the array to add the element to, may be {@code null}
4354      * @param index  the position of the new object
4355      * @param element  the object to add
4356      * @return A new array containing the existing elements and the new element
4357      * @throws IndexOutOfBoundsException if the index is out of range
4358      * (index &lt; 0 || index &gt; array.length).
4359      */
4360     public static char[] add(final char[] array, final int index, final char element) {
4361         return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
4362     }
4363 
4364     /**
4365      * <p>Inserts the specified element at the specified position in the array.
4366      * Shifts the element currently at that position (if any) and any subsequent
4367      * elements to the right (adds one to their indices).</p>
4368      *
4369      * <p>This method returns a new array with the same elements of the input
4370      * array plus the given element on the specified position. The component
4371      * type of the returned array is always the same as that of the input
4372      * array.</p>
4373      *
4374      * <p>If the input array is {@code null}, a new one element array is returned
4375      *  whose component type is the same as the element.</p>
4376      *
4377      * <pre>
4378      * ArrayUtils.add([1], 0, 2)         = [2, 1]
4379      * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
4380      * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
4381      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4382      * </pre>
4383      *
4384      * @param array  the array to add the element to, may be {@code null}
4385      * @param index  the position of the new object
4386      * @param element  the object to add
4387      * @return A new array containing the existing elements and the new element
4388      * @throws IndexOutOfBoundsException if the index is out of range
4389      * (index &lt; 0 || index &gt; array.length).
4390      */
4391     public static byte[] add(final byte[] array, final int index, final byte element) {
4392         return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
4393     }
4394 
4395     /**
4396      * <p>Inserts the specified element at the specified position in the array.
4397      * Shifts the element currently at that position (if any) and any subsequent
4398      * elements to the right (adds one to their indices).</p>
4399      *
4400      * <p>This method returns a new array with the same elements of the input
4401      * array plus the given element on the specified position. The component
4402      * type of the returned array is always the same as that of the input
4403      * array.</p>
4404      *
4405      * <p>If the input array is {@code null}, a new one element array is returned
4406      *  whose component type is the same as the element.</p>
4407      *
4408      * <pre>
4409      * ArrayUtils.add([1], 0, 2)         = [2, 1]
4410      * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
4411      * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
4412      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4413      * </pre>
4414      *
4415      * @param array  the array to add the element to, may be {@code null}
4416      * @param index  the position of the new object
4417      * @param element  the object to add
4418      * @return A new array containing the existing elements and the new element
4419      * @throws IndexOutOfBoundsException if the index is out of range
4420      * (index &lt; 0 || index &gt; array.length).
4421      */
4422     public static short[] add(final short[] array, final int index, final short element) {
4423         return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
4424     }
4425 
4426     /**
4427      * <p>Inserts the specified element at the specified position in the array.
4428      * Shifts the element currently at that position (if any) and any subsequent
4429      * elements to the right (adds one to their indices).</p>
4430      *
4431      * <p>This method returns a new array with the same elements of the input
4432      * array plus the given element on the specified position. The component
4433      * type of the returned array is always the same as that of the input
4434      * array.</p>
4435      *
4436      * <p>If the input array is {@code null}, a new one element array is returned
4437      *  whose component type is the same as the element.</p>
4438      *
4439      * <pre>
4440      * ArrayUtils.add([1], 0, 2)         = [2, 1]
4441      * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
4442      * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
4443      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4444      * </pre>
4445      *
4446      * @param array  the array to add the element to, may be {@code null}
4447      * @param index  the position of the new object
4448      * @param element  the object to add
4449      * @return A new array containing the existing elements and the new element
4450      * @throws IndexOutOfBoundsException if the index is out of range
4451      * (index &lt; 0 || index &gt; array.length).
4452      */
4453     public static int[] add(final int[] array, final int index, final int element) {
4454         return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
4455     }
4456 
4457     /**
4458      * <p>Inserts the specified element at the specified position in the array.
4459      * Shifts the element currently at that position (if any) and any subsequent
4460      * elements to the right (adds one to their indices).</p>
4461      *
4462      * <p>This method returns a new array with the same elements of the input
4463      * array plus the given element on the specified position. The component
4464      * type of the returned array is always the same as that of the input
4465      * array.</p>
4466      *
4467      * <p>If the input array is {@code null}, a new one element array is returned
4468      *  whose component type is the same as the element.</p>
4469      *
4470      * <pre>
4471      * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
4472      * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
4473      * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
4474      * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
4475      * </pre>
4476      *
4477      * @param array  the array to add the element to, may be {@code null}
4478      * @param index  the position of the new object
4479      * @param element  the object to add
4480      * @return A new array containing the existing elements and the new element
4481      * @throws IndexOutOfBoundsException if the index is out of range
4482      * (index &lt; 0 || index &gt; array.length).
4483      */
4484     public static long[] add(final long[] array, final int index, final long element) {
4485         return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
4486     }
4487 
4488     /**
4489      * <p>Inserts the specified element at the specified position in the array.
4490      * Shifts the element currently at that position (if any) and any subsequent
4491      * elements to the right (adds one to their indices).</p>
4492      *
4493      * <p>This method returns a new array with the same elements of the input
4494      * array plus the given element on the specified position. The component
4495      * type of the returned array is always the same as that of the input
4496      * array.</p>
4497      *
4498      * <p>If the input array is {@code null}, a new one element array is returned
4499      *  whose component type is the same as the element.</p>
4500      *
4501      * <pre>
4502      * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
4503      * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
4504      * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
4505      * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
4506      * </pre>
4507      *
4508      * @param array  the array to add the element to, may be {@code null}
4509      * @param index  the position of the new object
4510      * @param element  the object to add
4511      * @return A new array containing the existing elements and the new element
4512      * @throws IndexOutOfBoundsException if the index is out of range
4513      * (index &lt; 0 || index &gt; array.length).
4514      */
4515     public static float[] add(final float[] array, final int index, final float element) {
4516         return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
4517     }
4518 
4519     /**
4520      * <p>Inserts the specified element at the specified position in the array.
4521      * Shifts the element currently at that position (if any) and any subsequent
4522      * elements to the right (adds one to their indices).</p>
4523      *
4524      * <p>This method returns a new array with the same elements of the input
4525      * array plus the given element on the specified position. The component
4526      * type of the returned array is always the same as that of the input
4527      * array.</p>
4528      *
4529      * <p>If the input array is {@code null}, a new one element array is returned
4530      *  whose component type is the same as the element.</p>
4531      *
4532      * <pre>
4533      * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
4534      * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
4535      * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
4536      * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
4537      * </pre>
4538      *
4539      * @param array  the array to add the element to, may be {@code null}
4540      * @param index  the position of the new object
4541      * @param element  the object to add
4542      * @return A new array containing the existing elements and the new element
4543      * @throws IndexOutOfBoundsException if the index is out of range
4544      * (index &lt; 0 || index &gt; array.length).
4545      */
4546     public static double[] add(final double[] array, final int index, final double element) {
4547         return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
4548     }
4549 
4550     /**
4551      * Underlying implementation of add(array, index, element) methods.
4552      * The last parameter is the class, which may not equal element.getClass
4553      * for primitives.
4554      *
4555      * @param array  the array to add the element to, may be {@code null}
4556      * @param index  the position of the new object
4557      * @param element  the object to add
4558      * @param clss the type of the element being added
4559      * @return A new array containing the existing elements and the new element
4560      */
4561     private static Object add(final Object array, final int index, final Object element, final Class<?> clss) {
4562         if (array == null) {
4563             if (index != 0) {
4564                 throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
4565             }
4566             final Object joinedArray = Array.newInstance(clss, 1);
4567             Array.set(joinedArray, 0, element);
4568             return joinedArray;
4569         }
4570         final int length = Array.getLength(array);
4571         if (index > length || index < 0) {
4572             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
4573         }
4574         final Object result = Array.newInstance(clss, length + 1);
4575         System.arraycopy(array, 0, result, 0, index);
4576         Array.set(result, index, element);
4577         if (index < length) {
4578             System.arraycopy(array, index, result, index + 1, length - index);
4579         }
4580         return result;
4581     }
4582 
4583     /**
4584      * <p>Removes the element at the specified position from the specified array.
4585      * All subsequent elements are shifted to the left (subtracts one from
4586      * their indices).</p>
4587      *
4588      * <p>This method returns a new array with the same elements of the input
4589      * array except the element on the specified position. The component
4590      * type of the returned array is always the same as that of the input
4591      * array.</p>
4592      *
4593      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4594      * will be thrown, because in that case no valid index can be specified.</p>
4595      *
4596      * <pre>
4597      * ArrayUtils.remove(["a"], 0)           = []
4598      * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
4599      * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
4600      * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
4601      * </pre>
4602      *
4603      * @param <T> the component type of the array
4604      * @param array  the array to remove the element from, may not be {@code null}
4605      * @param index  the position of the element to be removed
4606      * @return A new array containing the existing elements except the element
4607      *         at the specified position.
4608      * @throws IndexOutOfBoundsException if the index is out of range
4609      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4610      * @since 2.1
4611      */
4612     @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
4613     public static <T> T[] remove(final T[] array, final int index) {
4614         return (T[]) remove((Object) array, index);
4615     }
4616 
4617     /**
4618      * <p>Removes the first occurrence of the specified element from the
4619      * specified array. All subsequent elements are shifted to the left
4620      * (subtracts one from their indices). If the array doesn't contains
4621      * such an element, no elements are removed from the array.</p>
4622      *
4623      * <p>This method returns a new array with the same elements of the input
4624      * array except the first occurrence of the specified element. The component
4625      * type of the returned array is always the same as that of the input
4626      * array.</p>
4627      *
4628      * <pre>
4629      * ArrayUtils.removeElement(null, "a")            = null
4630      * ArrayUtils.removeElement([], "a")              = []
4631      * ArrayUtils.removeElement(["a"], "b")           = ["a"]
4632      * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
4633      * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
4634      * </pre>
4635      *
4636      * @param <T> the component type of the array
4637      * @param array  the array to remove the element from, may be {@code null}
4638      * @param element  the element to be removed
4639      * @return A new array containing the existing elements except the first
4640      *         occurrence of the specified element.
4641      * @since 2.1
4642      */
4643     public static <T> T[] removeElement(final T[] array, final Object element) {
4644         final int index = indexOf(array, element);
4645         if (index == INDEX_NOT_FOUND) {
4646             return clone(array);
4647         }
4648         return remove(array, index);
4649     }
4650 
4651     /**
4652      * <p>Removes the element at the specified position from the specified array.
4653      * All subsequent elements are shifted to the left (subtracts one from
4654      * their indices).</p>
4655      *
4656      * <p>This method returns a new array with the same elements of the input
4657      * array except the element on the specified position. The component
4658      * type of the returned array is always the same as that of the input
4659      * array.</p>
4660      *
4661      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4662      * will be thrown, because in that case no valid index can be specified.</p>
4663      *
4664      * <pre>
4665      * ArrayUtils.remove([true], 0)              = []
4666      * ArrayUtils.remove([true, false], 0)       = [false]
4667      * ArrayUtils.remove([true, false], 1)       = [true]
4668      * ArrayUtils.remove([true, true, false], 1) = [true, false]
4669      * </pre>
4670      *
4671      * @param array  the array to remove the element from, may not be {@code null}
4672      * @param index  the position of the element to be removed
4673      * @return A new array containing the existing elements except the element
4674      *         at the specified position.
4675      * @throws IndexOutOfBoundsException if the index is out of range
4676      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4677      * @since 2.1
4678      */
4679     public static boolean[] remove(final boolean[] array, final int index) {
4680         return (boolean[]) remove((Object) array, index);
4681     }
4682 
4683     /**
4684      * <p>Removes the first occurrence of the specified element from the
4685      * specified array. All subsequent elements are shifted to the left
4686      * (subtracts one from their indices). If the array doesn't contains
4687      * such an element, no elements are removed from the array.</p>
4688      *
4689      * <p>This method returns a new array with the same elements of the input
4690      * array except the first occurrence of the specified element. The component
4691      * type of the returned array is always the same as that of the input
4692      * array.</p>
4693      *
4694      * <pre>
4695      * ArrayUtils.removeElement(null, true)                = null
4696      * ArrayUtils.removeElement([], true)                  = []
4697      * ArrayUtils.removeElement([true], false)             = [true]
4698      * ArrayUtils.removeElement([true, false], false)      = [true]
4699      * ArrayUtils.removeElement([true, false, true], true) = [false, true]
4700      * </pre>
4701      *
4702      * @param array  the array to remove the element from, may be {@code null}
4703      * @param element  the element to be removed
4704      * @return A new array containing the existing elements except the first
4705      *         occurrence of the specified element.
4706      * @since 2.1
4707      */
4708     public static boolean[] removeElement(final boolean[] array, final boolean element) {
4709         final int index = indexOf(array, element);
4710         if (index == INDEX_NOT_FOUND) {
4711             return clone(array);
4712         }
4713         return remove(array, index);
4714     }
4715 
4716     /**
4717      * <p>Removes the element at the specified position from the specified array.
4718      * All subsequent elements are shifted to the left (subtracts one from
4719      * their indices).</p>
4720      *
4721      * <p>This method returns a new array with the same elements of the input
4722      * array except the element on the specified position. The component
4723      * type of the returned array is always the same as that of the input
4724      * array.</p>
4725      *
4726      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4727      * will be thrown, because in that case no valid index can be specified.</p>
4728      *
4729      * <pre>
4730      * ArrayUtils.remove([1], 0)          = []
4731      * ArrayUtils.remove([1, 0], 0)       = [0]
4732      * ArrayUtils.remove([1, 0], 1)       = [1]
4733      * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
4734      * </pre>
4735      *
4736      * @param array  the array to remove the element from, may not be {@code null}
4737      * @param index  the position of the element to be removed
4738      * @return A new array containing the existing elements except the element
4739      *         at the specified position.
4740      * @throws IndexOutOfBoundsException if the index is out of range
4741      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4742      * @since 2.1
4743      */
4744     public static byte[] remove(final byte[] array, final int index) {
4745         return (byte[]) remove((Object) array, index);
4746     }
4747 
4748     /**
4749      * <p>Removes the first occurrence of the specified element from the
4750      * specified array. All subsequent elements are shifted to the left
4751      * (subtracts one from their indices). If the array doesn't contains
4752      * such an element, no elements are removed from the array.</p>
4753      *
4754      * <p>This method returns a new array with the same elements of the input
4755      * array except the first occurrence of the specified element. The component
4756      * type of the returned array is always the same as that of the input
4757      * array.</p>
4758      *
4759      * <pre>
4760      * ArrayUtils.removeElement(null, 1)        = null
4761      * ArrayUtils.removeElement([], 1)          = []
4762      * ArrayUtils.removeElement([1], 0)         = [1]
4763      * ArrayUtils.removeElement([1, 0], 0)      = [1]
4764      * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
4765      * </pre>
4766      *
4767      * @param array  the array to remove the element from, may be {@code null}
4768      * @param element  the element to be removed
4769      * @return A new array containing the existing elements except the first
4770      *         occurrence of the specified element.
4771      * @since 2.1
4772      */
4773     public static byte[] removeElement(final byte[] array, final byte element) {
4774         final int index = indexOf(array, element);
4775         if (index == INDEX_NOT_FOUND) {
4776             return clone(array);
4777         }
4778         return remove(array, index);
4779     }
4780 
4781     /**
4782      * <p>Removes the element at the specified position from the specified array.
4783      * All subsequent elements are shifted to the left (subtracts one from
4784      * their indices).</p>
4785      *
4786      * <p>This method returns a new array with the same elements of the input
4787      * array except the element on the specified position. The component
4788      * type of the returned array is always the same as that of the input
4789      * array.</p>
4790      *
4791      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4792      * will be thrown, because in that case no valid index can be specified.</p>
4793      *
4794      * <pre>
4795      * ArrayUtils.remove(['a'], 0)           = []
4796      * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
4797      * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
4798      * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
4799      * </pre>
4800      *
4801      * @param array  the array to remove the element from, may not be {@code null}
4802      * @param index  the position of the element to be removed
4803      * @return A new array containing the existing elements except the element
4804      *         at the specified position.
4805      * @throws IndexOutOfBoundsException if the index is out of range
4806      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4807      * @since 2.1
4808      */
4809     public static char[] remove(final char[] array, final int index) {
4810         return (char[]) remove((Object) array, index);
4811     }
4812 
4813     /**
4814      * <p>Removes the first occurrence of the specified element from the
4815      * specified array. All subsequent elements are shifted to the left
4816      * (subtracts one from their indices). If the array doesn't contains
4817      * such an element, no elements are removed from the array.</p>
4818      *
4819      * <p>This method returns a new array with the same elements of the input
4820      * array except the first occurrence of the specified element. The component
4821      * type of the returned array is always the same as that of the input
4822      * array.</p>
4823      *
4824      * <pre>
4825      * ArrayUtils.removeElement(null, 'a')            = null
4826      * ArrayUtils.removeElement([], 'a')              = []
4827      * ArrayUtils.removeElement(['a'], 'b')           = ['a']
4828      * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
4829      * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
4830      * </pre>
4831      *
4832      * @param array  the array to remove the element from, may be {@code null}
4833      * @param element  the element to be removed
4834      * @return A new array containing the existing elements except the first
4835      *         occurrence of the specified element.
4836      * @since 2.1
4837      */
4838     public static char[] removeElement(final char[] array, final char element) {
4839         final int index = indexOf(array, element);
4840         if (index == INDEX_NOT_FOUND) {
4841             return clone(array);
4842         }
4843         return remove(array, index);
4844     }
4845 
4846     /**
4847      * <p>Removes the element at the specified position from the specified array.
4848      * All subsequent elements are shifted to the left (subtracts one from
4849      * their indices).</p>
4850      *
4851      * <p>This method returns a new array with the same elements of the input
4852      * array except the element on the specified position. The component
4853      * type of the returned array is always the same as that of the input
4854      * array.</p>
4855      *
4856      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4857      * will be thrown, because in that case no valid index can be specified.</p>
4858      *
4859      * <pre>
4860      * ArrayUtils.remove([1.1], 0)           = []
4861      * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4862      * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4863      * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4864      * </pre>
4865      *
4866      * @param array  the array to remove the element from, may not be {@code null}
4867      * @param index  the position of the element to be removed
4868      * @return A new array containing the existing elements except the element
4869      *         at the specified position.
4870      * @throws IndexOutOfBoundsException if the index is out of range
4871      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4872      * @since 2.1
4873      */
4874     public static double[] remove(final double[] array, final int index) {
4875         return (double[]) remove((Object) array, index);
4876     }
4877 
4878     /**
4879      * <p>Removes the first occurrence of the specified element from the
4880      * specified array. All subsequent elements are shifted to the left
4881      * (subtracts one from their indices). If the array doesn't contains
4882      * such an element, no elements are removed from the array.</p>
4883      *
4884      * <p>This method returns a new array with the same elements of the input
4885      * array except the first occurrence of the specified element. The component
4886      * type of the returned array is always the same as that of the input
4887      * array.</p>
4888      *
4889      * <pre>
4890      * ArrayUtils.removeElement(null, 1.1)            = null
4891      * ArrayUtils.removeElement([], 1.1)              = []
4892      * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
4893      * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
4894      * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
4895      * </pre>
4896      *
4897      * @param array  the array to remove the element from, may be {@code null}
4898      * @param element  the element to be removed
4899      * @return A new array containing the existing elements except the first
4900      *         occurrence of the specified element.
4901      * @since 2.1
4902      */
4903     public static double[] removeElement(final double[] array, final double element) {
4904         final int index = indexOf(array, element);
4905         if (index == INDEX_NOT_FOUND) {
4906             return clone(array);
4907         }
4908         return remove(array, index);
4909     }
4910 
4911     /**
4912      * <p>Removes the element at the specified position from the specified array.
4913      * All subsequent elements are shifted to the left (subtracts one from
4914      * their indices).</p>
4915      *
4916      * <p>This method returns a new array with the same elements of the input
4917      * array except the element on the specified position. The component
4918      * type of the returned array is always the same as that of the input
4919      * array.</p>
4920      *
4921      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4922      * will be thrown, because in that case no valid index can be specified.</p>
4923      *
4924      * <pre>
4925      * ArrayUtils.remove([1.1], 0)           = []
4926      * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4927      * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4928      * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4929      * </pre>
4930      *
4931      * @param array  the array to remove the element from, may not be {@code null}
4932      * @param index  the position of the element to be removed
4933      * @return A new array containing the existing elements except the element
4934      *         at the specified position.
4935      * @throws IndexOutOfBoundsException if the index is out of range
4936      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4937      * @since 2.1
4938      */
4939     public static float[] remove(final float[] array, final int index) {
4940         return (float[]) remove((Object) array, index);
4941     }
4942 
4943     /**
4944      * <p>Removes the first occurrence of the specified element from the
4945      * specified array. All subsequent elements are shifted to the left
4946      * (subtracts one from their indices). If the array doesn't contains
4947      * such an element, no elements are removed from the array.</p>
4948      *
4949      * <p>This method returns a new array with the same elements of the input
4950      * array except the first occurrence of the specified element. The component
4951      * type of the returned array is always the same as that of the input
4952      * array.</p>
4953      *
4954      * <pre>
4955      * ArrayUtils.removeElement(null, 1.1)            = null
4956      * ArrayUtils.removeElement([], 1.1)              = []
4957      * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
4958      * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
4959      * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
4960      * </pre>
4961      *
4962      * @param array  the array to remove the element from, may be {@code null}
4963      * @param element  the element to be removed
4964      * @return A new array containing the existing elements except the first
4965      *         occurrence of the specified element.
4966      * @since 2.1
4967      */
4968     public static float[] removeElement(final float[] array, final float element) {
4969         final int index = indexOf(array, element);
4970         if (index == INDEX_NOT_FOUND) {
4971             return clone(array);
4972         }
4973         return remove(array, index);
4974     }
4975 
4976     /**
4977      * <p>Removes the element at the specified position from the specified array.
4978      * All subsequent elements are shifted to the left (subtracts one from
4979      * their indices).</p>
4980      *
4981      * <p>This method returns a new array with the same elements of the input
4982      * array except the element on the specified position. The component
4983      * type of the returned array is always the same as that of the input
4984      * array.</p>
4985      *
4986      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4987      * will be thrown, because in that case no valid index can be specified.</p>
4988      *
4989      * <pre>
4990      * ArrayUtils.remove([1], 0)         = []
4991      * ArrayUtils.remove([2, 6], 0)      = [6]
4992      * ArrayUtils.remove([2, 6], 1)      = [2]
4993      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4994      * </pre>
4995      *
4996      * @param array  the array to remove the element from, may not be {@code null}
4997      * @param index  the position of the element to be removed
4998      * @return A new array containing the existing elements except the element
4999      *         at the specified position.
5000      * @throws IndexOutOfBoundsException if the index is out of range
5001      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5002      * @since 2.1
5003      */
5004     public static int[] remove(final int[] array, final int index) {
5005         return (int[]) remove((Object) array, index);
5006     }
5007 
5008     /**
5009      * <p>Removes the first occurrence of the specified element from the
5010      * specified array. All subsequent elements are shifted to the left
5011      * (subtracts one from their indices). If the array doesn't contains
5012      * such an element, no elements are removed from the array.</p>
5013      *
5014      * <p>This method returns a new array with the same elements of the input
5015      * array except the first occurrence of the specified element. The component
5016      * type of the returned array is always the same as that of the input
5017      * array.</p>
5018      *
5019      * <pre>
5020      * ArrayUtils.removeElement(null, 1)      = null
5021      * ArrayUtils.removeElement([], 1)        = []
5022      * ArrayUtils.removeElement([1], 2)       = [1]
5023      * ArrayUtils.removeElement([1, 3], 1)    = [3]
5024      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5025      * </pre>
5026      *
5027      * @param array  the array to remove the element from, may be {@code null}
5028      * @param element  the element to be removed
5029      * @return A new array containing the existing elements except the first
5030      *         occurrence of the specified element.
5031      * @since 2.1
5032      */
5033     public static int[] removeElement(final int[] array, final int element) {
5034         final int index = indexOf(array, element);
5035         if (index == INDEX_NOT_FOUND) {
5036             return clone(array);
5037         }
5038         return remove(array, index);
5039     }
5040 
5041     /**
5042      * <p>Removes the element at the specified position from the specified array.
5043      * All subsequent elements are shifted to the left (subtracts one from
5044      * their indices).</p>
5045      *
5046      * <p>This method returns a new array with the same elements of the input
5047      * array except the element on the specified position. The component
5048      * type of the returned array is always the same as that of the input
5049      * array.</p>
5050      *
5051      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5052      * will be thrown, because in that case no valid index can be specified.</p>
5053      *
5054      * <pre>
5055      * ArrayUtils.remove([1], 0)         = []
5056      * ArrayUtils.remove([2, 6], 0)      = [6]
5057      * ArrayUtils.remove([2, 6], 1)      = [2]
5058      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5059      * </pre>
5060      *
5061      * @param array  the array to remove the element from, may not be {@code null}
5062      * @param index  the position of the element to be removed
5063      * @return A new array containing the existing elements except the element
5064      *         at the specified position.
5065      * @throws IndexOutOfBoundsException if the index is out of range
5066      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5067      * @since 2.1
5068      */
5069     public static long[] remove(final long[] array, final int index) {
5070         return (long[]) remove((Object) array, index);
5071     }
5072 
5073     /**
5074      * <p>Removes the first occurrence of the specified element from the
5075      * specified array. All subsequent elements are shifted to the left
5076      * (subtracts one from their indices). If the array doesn't contains
5077      * such an element, no elements are removed from the array.</p>
5078      *
5079      * <p>This method returns a new array with the same elements of the input
5080      * array except the first occurrence of the specified element. The component
5081      * type of the returned array is always the same as that of the input
5082      * array.</p>
5083      *
5084      * <pre>
5085      * ArrayUtils.removeElement(null, 1)      = null
5086      * ArrayUtils.removeElement([], 1)        = []
5087      * ArrayUtils.removeElement([1], 2)       = [1]
5088      * ArrayUtils.removeElement([1, 3], 1)    = [3]
5089      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5090      * </pre>
5091      *
5092      * @param array  the array to remove the element from, may be {@code null}
5093      * @param element  the element to be removed
5094      * @return A new array containing the existing elements except the first
5095      *         occurrence of the specified element.
5096      * @since 2.1
5097      */
5098     public static long[] removeElement(final long[] array, final long element) {
5099         final int index = indexOf(array, element);
5100         if (index == INDEX_NOT_FOUND) {
5101             return clone(array);
5102         }
5103         return remove(array, index);
5104     }
5105 
5106     /**
5107      * <p>Removes the element at the specified position from the specified array.
5108      * All subsequent elements are shifted to the left (subtracts one from
5109      * their indices).</p>
5110      *
5111      * <p>This method returns a new array with the same elements of the input
5112      * array except the element on the specified position. The component
5113      * type of the returned array is always the same as that of the input
5114      * array.</p>
5115      *
5116      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5117      * will be thrown, because in that case no valid index can be specified.</p>
5118      *
5119      * <pre>
5120      * ArrayUtils.remove([1], 0)         = []
5121      * ArrayUtils.remove([2, 6], 0)      = [6]
5122      * ArrayUtils.remove([2, 6], 1)      = [2]
5123      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5124      * </pre>
5125      *
5126      * @param array  the array to remove the element from, may not be {@code null}
5127      * @param index  the position of the element to be removed
5128      * @return A new array containing the existing elements except the element
5129      *         at the specified position.
5130      * @throws IndexOutOfBoundsException if the index is out of range
5131      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5132      * @since 2.1
5133      */
5134     public static short[] remove(final short[] array, final int index) {
5135         return (short[]) remove((Object) array, index);
5136     }
5137 
5138     /**
5139      * <p>Removes the first occurrence of the specified element from the
5140      * specified array. All subsequent elements are shifted to the left
5141      * (subtracts one from their indices). If the array doesn't contains
5142      * such an element, no elements are removed from the array.</p>
5143      *
5144      * <p>This method returns a new array with the same elements of the input
5145      * array except the first occurrence of the specified element. The component
5146      * type of the returned array is always the same as that of the input
5147      * array.</p>
5148      *
5149      * <pre>
5150      * ArrayUtils.removeElement(null, 1)      = null
5151      * ArrayUtils.removeElement([], 1)        = []
5152      * ArrayUtils.removeElement([1], 2)       = [1]
5153      * ArrayUtils.removeElement([1, 3], 1)    = [3]
5154      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5155      * </pre>
5156      *
5157      * @param array  the array to remove the element from, may be {@code null}
5158      * @param element  the element to be removed
5159      * @return A new array containing the existing elements except the first
5160      *         occurrence of the specified element.
5161      * @since 2.1
5162      */
5163     public static short[] removeElement(final short[] array, final short element) {
5164         final int index = indexOf(array, element);
5165         if (index == INDEX_NOT_FOUND) {
5166             return clone(array);
5167         }
5168         return remove(array, index);
5169     }
5170 
5171     /**
5172      * <p>Removes the element at the specified position from the specified array.
5173      * All subsequent elements are shifted to the left (subtracts one from
5174      * their indices).</p>
5175      *
5176      * <p>This method returns a new array with the same elements of the input
5177      * array except the element on the specified position. The component
5178      * type of the returned array is always the same as that of the input
5179      * array.</p>
5180      *
5181      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5182      * will be thrown, because in that case no valid index can be specified.</p>
5183      *
5184      * @param array  the array to remove the element from, may not be {@code null}
5185      * @param index  the position of the element to be removed
5186      * @return A new array containing the existing elements except the element
5187      *         at the specified position.
5188      * @throws IndexOutOfBoundsException if the index is out of range
5189      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5190      * @since 2.1
5191      */
5192     private static Object remove(final Object array, final int index) {
5193         final int length = getLength(array);
5194         if (index < 0 || index >= length) {
5195             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5196         }
5197 
5198         final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
5199         System.arraycopy(array, 0, result, 0, index);
5200         if (index < length - 1) {
5201             System.arraycopy(array, index + 1, result, index, length - index - 1);
5202         }
5203 
5204         return result;
5205     }
5206 
5207     /**
5208      * <p>Removes the elements at the specified positions from the specified array.
5209      * All remaining elements are shifted to the left.</p>
5210      *
5211      * <p>This method returns a new array with the same elements of the input
5212      * array except those at the specified positions. The component
5213      * type of the returned array is always the same as that of the input
5214      * array.</p>
5215      *
5216      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5217      * will be thrown, because in that case no valid index can be specified.</p>
5218      *
5219      * <pre>
5220      * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
5221      * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
5222      * </pre>
5223      *
5224      * @param <T> the component type of the array
5225      * @param array   the array to remove the element from, may not be {@code null}
5226      * @param indices the positions of the elements to be removed
5227      * @return A new array containing the existing elements except those
5228      *         at the specified positions.
5229      * @throws IndexOutOfBoundsException if any index is out of range
5230      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5231      * @since 3.0.1
5232      */
5233     @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5234     public static <T> T[] removeAll(final T[] array, final int... indices) {
5235         return (T[]) removeAll((Object) array, clone(indices));
5236     }
5237 
5238     /**
5239      * <p>Removes occurrences of specified elements, in specified quantities,
5240      * from the specified array. All subsequent elements are shifted left.
5241      * For any element-to-be-removed specified in greater quantities than
5242      * contained in the original array, no change occurs beyond the
5243      * removal of the existing matching items.</p>
5244      *
5245      * <p>This method returns a new array with the same elements of the input
5246      * array except for the earliest-encountered occurrences of the specified
5247      * elements. The component type of the returned array is always the same
5248      * as that of the input array.</p>
5249      *
5250      * <pre>
5251      * ArrayUtils.removeElements(null, "a", "b")            = null
5252      * ArrayUtils.removeElements([], "a", "b")              = []
5253      * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
5254      * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
5255      * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
5256      * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
5257      * </pre>
5258      *
5259      * @param <T> the component type of the array
5260      * @param array  the array to remove the element from, may be {@code null}
5261      * @param values the elements to be removed
5262      * @return A new array containing the existing elements except the
5263      *         earliest-encountered occurrences of the specified elements.
5264      * @since 3.0.1
5265      */
5266     public static <T> T[] removeElements(final T[] array, final T... values) {
5267         if (isEmpty(array) || isEmpty(values)) {
5268             return clone(array);
5269         }
5270         final HashMap<T, MutableInt> occurrences = new HashMap<T, MutableInt>(values.length);
5271         for (final T v : values) {
5272             final MutableInt count = occurrences.get(v);
5273             if (count == null) {
5274                 occurrences.put(v, new MutableInt(1));
5275             } else {
5276                 count.increment();
5277             }
5278         }
5279         final BitSet toRemove = new BitSet();
5280         for (final Map.Entry<T, MutableInt> e : occurrences.entrySet()) {
5281             final T v = e.getKey();
5282             int found = 0;
5283             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5284                 found = indexOf(array, v, found);
5285                 if (found < 0) {
5286                     break;
5287                 }
5288                 toRemove.set(found++);
5289             }
5290         }
5291         @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5292         final
5293         T[] result = (T[]) removeAll(array, toRemove);
5294         return result;
5295     }
5296 
5297     /**
5298      * <p>Removes the elements at the specified positions from the specified array.
5299      * All remaining elements are shifted to the left.</p>
5300      *
5301      * <p>This method returns a new array with the same elements of the input
5302      * array except those at the specified positions. The component
5303      * type of the returned array is always the same as that of the input
5304      * array.</p>
5305      *
5306      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5307      * will be thrown, because in that case no valid index can be specified.</p>
5308      *
5309      * <pre>
5310      * ArrayUtils.removeAll([1], 0)             = []
5311      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5312      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5313      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5314      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5315      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5316      * </pre>
5317      *
5318      * @param array   the array to remove the element from, may not be {@code null}
5319      * @param indices the positions of the elements to be removed
5320      * @return A new array containing the existing elements except those
5321      *         at the specified positions.
5322      * @throws IndexOutOfBoundsException if any index is out of range
5323      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5324      * @since 3.0.1
5325      */
5326     public static byte[] removeAll(final byte[] array, final int... indices) {
5327         return (byte[]) removeAll((Object) array, clone(indices));
5328     }
5329 
5330     /**
5331      * <p>Removes occurrences of specified elements, in specified quantities,
5332      * from the specified array. All subsequent elements are shifted left.
5333      * For any element-to-be-removed specified in greater quantities than
5334      * contained in the original array, no change occurs beyond the
5335      * removal of the existing matching items.</p>
5336      *
5337      * <p>This method returns a new array with the same elements of the input
5338      * array except for the earliest-encountered occurrences of the specified
5339      * elements. The component type of the returned array is always the same
5340      * as that of the input array.</p>
5341      *
5342      * <pre>
5343      * ArrayUtils.removeElements(null, 1, 2)      = null
5344      * ArrayUtils.removeElements([], 1, 2)        = []
5345      * ArrayUtils.removeElements([1], 2, 3)       = [1]
5346      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5347      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5348      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5349      * </pre>
5350      *
5351      * @param array  the array to remove the element from, may be {@code null}
5352      * @param values the elements to be removed
5353      * @return A new array containing the existing elements except the
5354      *         earliest-encountered occurrences of the specified elements.
5355      * @since 3.0.1
5356      */
5357     public static byte[] removeElements(final byte[] array, final byte... values) {
5358         if (isEmpty(array) || isEmpty(values)) {
5359             return clone(array);
5360         }
5361         final Map<Byte, MutableInt> occurrences = new HashMap<Byte, MutableInt>(values.length);
5362         for (final byte v : values) {
5363             final Byte boxed = Byte.valueOf(v);
5364             final MutableInt count = occurrences.get(boxed);
5365             if (count == null) {
5366                 occurrences.put(boxed, new MutableInt(1));
5367             } else {
5368                 count.increment();
5369             }
5370         }
5371         final BitSet toRemove = new BitSet();
5372         for (final Map.Entry<Byte, MutableInt> e : occurrences.entrySet()) {
5373             final Byte v = e.getKey();
5374             int found = 0;
5375             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5376                 found = indexOf(array, v.byteValue(), found);
5377                 if (found < 0) {
5378                     break;
5379                 }
5380                 toRemove.set(found++);
5381             }
5382         }
5383         return (byte[]) removeAll(array, toRemove);
5384     }
5385 
5386     /**
5387      * <p>Removes the elements at the specified positions from the specified array.
5388      * All remaining elements are shifted to the left.</p>
5389      *
5390      * <p>This method returns a new array with the same elements of the input
5391      * array except those at the specified positions. The component
5392      * type of the returned array is always the same as that of the input
5393      * array.</p>
5394      *
5395      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5396      * will be thrown, because in that case no valid index can be specified.</p>
5397      *
5398      * <pre>
5399      * ArrayUtils.removeAll([1], 0)             = []
5400      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5401      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5402      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5403      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5404      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5405      * </pre>
5406      *
5407      * @param array   the array to remove the element from, may not be {@code null}
5408      * @param indices the positions of the elements to be removed
5409      * @return A new array containing the existing elements except those
5410      *         at the specified positions.
5411      * @throws IndexOutOfBoundsException if any index is out of range
5412      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5413      * @since 3.0.1
5414      */
5415     public static short[] removeAll(final short[] array, final int... indices) {
5416         return (short[]) removeAll((Object) array, clone(indices));
5417     }
5418 
5419     /**
5420      * <p>Removes occurrences of specified elements, in specified quantities,
5421      * from the specified array. All subsequent elements are shifted left.
5422      * For any element-to-be-removed specified in greater quantities than
5423      * contained in the original array, no change occurs beyond the
5424      * removal of the existing matching items.</p>
5425      *
5426      * <p>This method returns a new array with the same elements of the input
5427      * array except for the earliest-encountered occurrences of the specified
5428      * elements. The component type of the returned array is always the same
5429      * as that of the input array.</p>
5430      *
5431      * <pre>
5432      * ArrayUtils.removeElements(null, 1, 2)      = null
5433      * ArrayUtils.removeElements([], 1, 2)        = []
5434      * ArrayUtils.removeElements([1], 2, 3)       = [1]
5435      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5436      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5437      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5438      * </pre>
5439      *
5440      * @param array  the array to remove the element from, may be {@code null}
5441      * @param values the elements to be removed
5442      * @return A new array containing the existing elements except the
5443      *         earliest-encountered occurrences of the specified elements.
5444      * @since 3.0.1
5445      */
5446     public static short[] removeElements(final short[] array, final short... values) {
5447         if (isEmpty(array) || isEmpty(values)) {
5448             return clone(array);
5449         }
5450         final HashMap<Short, MutableInt> occurrences = new HashMap<Short, MutableInt>(values.length);
5451         for (final short v : values) {
5452             final Short boxed = Short.valueOf(v);
5453             final MutableInt count = occurrences.get(boxed);
5454             if (count == null) {
5455                 occurrences.put(boxed, new MutableInt(1));
5456             } else {
5457                 count.increment();
5458             }
5459         }
5460         final BitSet toRemove = new BitSet();
5461         for (final Map.Entry<Short, MutableInt> e : occurrences.entrySet()) {
5462             final Short v = e.getKey();
5463             int found = 0;
5464             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5465                 found = indexOf(array, v.shortValue(), found);
5466                 if (found < 0) {
5467                     break;
5468                 }
5469                 toRemove.set(found++);
5470             }
5471         }
5472         return (short[]) removeAll(array, toRemove);
5473     }
5474 
5475     /**
5476      * <p>Removes the elements at the specified positions from the specified array.
5477      * All remaining elements are shifted to the left.</p>
5478      *
5479      * <p>This method returns a new array with the same elements of the input
5480      * array except those at the specified positions. The component
5481      * type of the returned array is always the same as that of the input
5482      * array.</p>
5483      *
5484      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5485      * will be thrown, because in that case no valid index can be specified.</p>
5486      *
5487      * <pre>
5488      * ArrayUtils.removeAll([1], 0)             = []
5489      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5490      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5491      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5492      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5493      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5494      * </pre>
5495      *
5496      * @param array   the array to remove the element from, may not be {@code null}
5497      * @param indices the positions of the elements to be removed
5498      * @return A new array containing the existing elements except those
5499      *         at the specified positions.
5500      * @throws IndexOutOfBoundsException if any index is out of range
5501      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5502      * @since 3.0.1
5503      */
5504     public static int[] removeAll(final int[] array, final int... indices) {
5505         return (int[]) removeAll((Object) array, clone(indices));
5506     }
5507 
5508     /**
5509      * <p>Removes occurrences of specified elements, in specified quantities,
5510      * from the specified array. All subsequent elements are shifted left.
5511      * For any element-to-be-removed specified in greater quantities than
5512      * contained in the original array, no change occurs beyond the
5513      * removal of the existing matching items.</p>
5514      *
5515      * <p>This method returns a new array with the same elements of the input
5516      * array except for the earliest-encountered occurrences of the specified
5517      * elements. The component type of the returned array is always the same
5518      * as that of the input array.</p>
5519      *
5520      * <pre>
5521      * ArrayUtils.removeElements(null, 1, 2)      = null
5522      * ArrayUtils.removeElements([], 1, 2)        = []
5523      * ArrayUtils.removeElements([1], 2, 3)       = [1]
5524      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5525      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5526      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5527      * </pre>
5528      *
5529      * @param array  the array to remove the element from, may be {@code null}
5530      * @param values the elements to be removed
5531      * @return A new array containing the existing elements except the
5532      *         earliest-encountered occurrences of the specified elements.
5533      * @since 3.0.1
5534      */
5535     public static int[] removeElements(final int[] array, final int... values) {
5536         if (isEmpty(array) || isEmpty(values)) {
5537             return clone(array);
5538         }
5539         final HashMap<Integer, MutableInt> occurrences = new HashMap<Integer, MutableInt>(values.length);
5540         for (final int v : values) {
5541             final Integer boxed = Integer.valueOf(v);
5542             final MutableInt count = occurrences.get(boxed);
5543             if (count == null) {
5544                 occurrences.put(boxed, new MutableInt(1));
5545             } else {
5546                 count.increment();
5547             }
5548         }
5549         final BitSet toRemove = new BitSet();
5550         for (final Map.Entry<Integer, MutableInt> e : occurrences.entrySet()) {
5551             final Integer v = e.getKey();
5552             int found = 0;
5553             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5554                 found = indexOf(array, v.intValue(), found);
5555                 if (found < 0) {
5556                     break;
5557                 }
5558                 toRemove.set(found++);
5559             }
5560         }
5561         return (int[]) removeAll(array, toRemove);
5562     }
5563 
5564     /**
5565      * <p>Removes the elements at the specified positions from the specified array.
5566      * All remaining elements are shifted to the left.</p>
5567      *
5568      * <p>This method returns a new array with the same elements of the input
5569      * array except those at the specified positions. The component
5570      * type of the returned array is always the same as that of the input
5571      * array.</p>
5572      *
5573      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5574      * will be thrown, because in that case no valid index can be specified.</p>
5575      *
5576      * <pre>
5577      * ArrayUtils.removeAll([1], 0)             = []
5578      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5579      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5580      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5581      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5582      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5583      * </pre>
5584      *
5585      * @param array   the array to remove the element from, may not be {@code null}
5586      * @param indices the positions of the elements to be removed
5587      * @return A new array containing the existing elements except those
5588      *         at the specified positions.
5589      * @throws IndexOutOfBoundsException if any index is out of range
5590      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5591      * @since 3.0.1
5592      */
5593     public static char[] removeAll(final char[] array, final int... indices) {
5594         return (char[]) removeAll((Object) array, clone(indices));
5595     }
5596 
5597     /**
5598      * <p>Removes occurrences of specified elements, in specified quantities,
5599      * from the specified array. All subsequent elements are shifted left.
5600      * For any element-to-be-removed specified in greater quantities than
5601      * contained in the original array, no change occurs beyond the
5602      * removal of the existing matching items.</p>
5603      *
5604      * <p>This method returns a new array with the same elements of the input
5605      * array except for the earliest-encountered occurrences of the specified
5606      * elements. The component type of the returned array is always the same
5607      * as that of the input array.</p>
5608      *
5609      * <pre>
5610      * ArrayUtils.removeElements(null, 1, 2)      = null
5611      * ArrayUtils.removeElements([], 1, 2)        = []
5612      * ArrayUtils.removeElements([1], 2, 3)       = [1]
5613      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5614      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5615      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5616      * </pre>
5617      *
5618      * @param array  the array to remove the element from, may be {@code null}
5619      * @param values the elements to be removed
5620      * @return A new array containing the existing elements except the
5621      *         earliest-encountered occurrences of the specified elements.
5622      * @since 3.0.1
5623      */
5624     public static char[] removeElements(final char[] array, final char... values) {
5625         if (isEmpty(array) || isEmpty(values)) {
5626             return clone(array);
5627         }
5628         final HashMap<Character, MutableInt> occurrences = new HashMap<Character, MutableInt>(values.length);
5629         for (final char v : values) {
5630             final Character boxed = Character.valueOf(v);
5631             final MutableInt count = occurrences.get(boxed);
5632             if (count == null) {
5633                 occurrences.put(boxed, new MutableInt(1));
5634             } else {
5635                 count.increment();
5636             }
5637         }
5638         final BitSet toRemove = new BitSet();
5639         for (final Map.Entry<Character, MutableInt> e : occurrences.entrySet()) {
5640             final Character v = e.getKey();
5641             int found = 0;
5642             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5643                 found = indexOf(array, v.charValue(), found);
5644                 if (found < 0) {
5645                     break;
5646                 }
5647                 toRemove.set(found++);
5648             }
5649         }
5650         return (char[]) removeAll(array, toRemove);
5651     }
5652 
5653     /**
5654      * <p>Removes the elements at the specified positions from the specified array.
5655      * All remaining elements are shifted to the left.</p>
5656      *
5657      * <p>This method returns a new array with the same elements of the input
5658      * array except those at the specified positions. The component
5659      * type of the returned array is always the same as that of the input
5660      * array.</p>
5661      *
5662      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5663      * will be thrown, because in that case no valid index can be specified.</p>
5664      *
5665      * <pre>
5666      * ArrayUtils.removeAll([1], 0)             = []
5667      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5668      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5669      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5670      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5671      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5672      * </pre>
5673      *
5674      * @param array   the array to remove the element from, may not be {@code null}
5675      * @param indices the positions of the elements to be removed
5676      * @return A new array containing the existing elements except those
5677      *         at the specified positions.
5678      * @throws IndexOutOfBoundsException if any index is out of range
5679      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5680      * @since 3.0.1
5681      */
5682     public static long[] removeAll(final long[] array, final int... indices) {
5683         return (long[]) removeAll((Object) array, clone(indices));
5684     }
5685 
5686     /**
5687      * <p>Removes occurrences of specified elements, in specified quantities,
5688      * from the specified array. All subsequent elements are shifted left.
5689      * For any element-to-be-removed specified in greater quantities than
5690      * contained in the original array, no change occurs beyond the
5691      * removal of the existing matching items.</p>
5692      *
5693      * <p>This method returns a new array with the same elements of the input
5694      * array except for the earliest-encountered occurrences of the specified
5695      * elements. The component type of the returned array is always the same
5696      * as that of the input array.</p>
5697      *
5698      * <pre>
5699      * ArrayUtils.removeElements(null, 1, 2)      = null
5700      * ArrayUtils.removeElements([], 1, 2)        = []
5701      * ArrayUtils.removeElements([1], 2, 3)       = [1]
5702      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5703      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5704      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5705      * </pre>
5706      *
5707      * @param array  the array to remove the element from, may be {@code null}
5708      * @param values the elements to be removed
5709      * @return A new array containing the existing elements except the
5710      *         earliest-encountered occurrences of the specified elements.
5711      * @since 3.0.1
5712      */
5713     public static long[] removeElements(final long[] array, final long... values) {
5714         if (isEmpty(array) || isEmpty(values)) {
5715             return clone(array);
5716         }
5717         final HashMap<Long, MutableInt> occurrences = new HashMap<Long, MutableInt>(values.length);
5718         for (final long v : values) {
5719             final Long boxed = Long.valueOf(v);
5720             final MutableInt count = occurrences.get(boxed);
5721             if (count == null) {
5722                 occurrences.put(boxed, new MutableInt(1));
5723             } else {
5724                 count.increment();
5725             }
5726         }
5727         final BitSet toRemove = new BitSet();
5728         for (final Map.Entry<Long, MutableInt> e : occurrences.entrySet()) {
5729             final Long v = e.getKey();
5730             int found = 0;
5731             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5732                 found = indexOf(array, v.longValue(), found);
5733                 if (found < 0) {
5734                     break;
5735                 }
5736                 toRemove.set(found++);
5737             }
5738         }
5739         return (long[]) removeAll(array, toRemove);
5740     }
5741 
5742     /**
5743      * <p>Removes the elements at the specified positions from the specified array.
5744      * All remaining elements are shifted to the left.</p>
5745      *
5746      * <p>This method returns a new array with the same elements of the input
5747      * array except those at the specified positions. The component
5748      * type of the returned array is always the same as that of the input
5749      * array.</p>
5750      *
5751      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5752      * will be thrown, because in that case no valid index can be specified.</p>
5753      *
5754      * <pre>
5755      * ArrayUtils.removeAll([1], 0)             = []
5756      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5757      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5758      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5759      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5760      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5761      * </pre>
5762      *
5763      * @param array   the array to remove the element from, may not be {@code null}
5764      * @param indices the positions of the elements to be removed
5765      * @return A new array containing the existing elements except those
5766      *         at the specified positions.
5767      * @throws IndexOutOfBoundsException if any index is out of range
5768      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5769      * @since 3.0.1
5770      */
5771     public static float[] removeAll(final float[] array, final int... indices) {
5772         return (float[]) removeAll((Object) array, clone(indices));
5773     }
5774 
5775     /**
5776      * <p>Removes occurrences of specified elements, in specified quantities,
5777      * from the specified array. All subsequent elements are shifted left.
5778      * For any element-to-be-removed specified in greater quantities than
5779      * contained in the original array, no change occurs beyond the
5780      * removal of the existing matching items.</p>
5781      *
5782      * <p>This method returns a new array with the same elements of the input
5783      * array except for the earliest-encountered occurrences of the specified
5784      * elements. The component type of the returned array is always the same
5785      * as that of the input array.</p>
5786      *
5787      * <pre>
5788      * ArrayUtils.removeElements(null, 1, 2)      = null
5789      * ArrayUtils.removeElements([], 1, 2)        = []
5790      * ArrayUtils.removeElements([1], 2, 3)       = [1]
5791      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5792      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5793      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5794      * </pre>
5795      *
5796      * @param array  the array to remove the element from, may be {@code null}
5797      * @param values the elements to be removed
5798      * @return A new array containing the existing elements except the
5799      *         earliest-encountered occurrences of the specified elements.
5800      * @since 3.0.1
5801      */
5802     public static float[] removeElements(final float[] array, final float... values) {
5803         if (isEmpty(array) || isEmpty(values)) {
5804             return clone(array);
5805         }
5806         final HashMap<Float, MutableInt> occurrences = new HashMap<Float, MutableInt>(values.length);
5807         for (final float v : values) {
5808             final Float boxed = Float.valueOf(v);
5809             final MutableInt count = occurrences.get(boxed);
5810             if (count == null) {
5811                 occurrences.put(boxed, new MutableInt(1));
5812             } else {
5813                 count.increment();
5814             }
5815         }
5816         final BitSet toRemove = new BitSet();
5817         for (final Map.Entry<Float, MutableInt> e : occurrences.entrySet()) {
5818             final Float v = e.getKey();
5819             int found = 0;
5820             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5821                 found = indexOf(array, v.floatValue(), found);
5822                 if (found < 0) {
5823                     break;
5824                 }
5825                 toRemove.set(found++);
5826             }
5827         }
5828         return (float[]) removeAll(array, toRemove);
5829     }
5830 
5831     /**
5832      * <p>Removes the elements at the specified positions from the specified array.
5833      * All remaining elements are shifted to the left.</p>
5834      *
5835      * <p>This method returns a new array with the same elements of the input
5836      * array except those at the specified positions. The component
5837      * type of the returned array is always the same as that of the input
5838      * array.</p>
5839      *
5840      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5841      * will be thrown, because in that case no valid index can be specified.</p>
5842      *
5843      * <pre>
5844      * ArrayUtils.removeAll([1], 0)             = []
5845      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5846      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5847      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5848      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5849      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5850      * </pre>
5851      *
5852      * @param array   the array to remove the element from, may not be {@code null}
5853      * @param indices the positions of the elements to be removed
5854      * @return A new array containing the existing elements except those
5855      *         at the specified positions.
5856      * @throws IndexOutOfBoundsException if any index is out of range
5857      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5858      * @since 3.0.1
5859      */
5860     public static double[] removeAll(final double[] array, final int... indices) {
5861         return (double[]) removeAll((Object) array, clone(indices));
5862     }
5863 
5864     /**
5865      * <p>Removes occurrences of specified elements, in specified quantities,
5866      * from the specified array. All subsequent elements are shifted left.
5867      * For any element-to-be-removed specified in greater quantities than
5868      * contained in the original array, no change occurs beyond the
5869      * removal of the existing matching items.</p>
5870      *
5871      * <p>This method returns a new array with the same elements of the input
5872      * array except for the earliest-encountered occurrences of the specified
5873      * elements. The component type of the returned array is always the same
5874      * as that of the input array.</p>
5875      *
5876      * <pre>
5877      * ArrayUtils.removeElements(null, 1, 2)      = null
5878      * ArrayUtils.removeElements([], 1, 2)        = []
5879      * ArrayUtils.removeElements([1], 2, 3)       = [1]
5880      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5881      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5882      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5883      * </pre>
5884      *
5885      * @param array  the array to remove the element from, may be {@code null}
5886      * @param values the elements to be removed
5887      * @return A new array containing the existing elements except the
5888      *         earliest-encountered occurrences of the specified elements.
5889      * @since 3.0.1
5890      */
5891     public static double[] removeElements(final double[] array, final double... values) {
5892         if (isEmpty(array) || isEmpty(values)) {
5893             return clone(array);
5894         }
5895         final HashMap<Double, MutableInt> occurrences = new HashMap<Double, MutableInt>(values.length);
5896         for (final double v : values) {
5897             final Double boxed = Double.valueOf(v);
5898             final MutableInt count = occurrences.get(boxed);
5899             if (count == null) {
5900                 occurrences.put(boxed, new MutableInt(1));
5901             } else {
5902                 count.increment();
5903             }
5904         }
5905         final BitSet toRemove = new BitSet();
5906         for (final Map.Entry<Double, MutableInt> e : occurrences.entrySet()) {
5907             final Double v = e.getKey();
5908             int found = 0;
5909             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5910                 found = indexOf(array, v.doubleValue(), found);
5911                 if (found < 0) {
5912                     break;
5913                 }
5914                 toRemove.set(found++);
5915             }
5916         }
5917         return (double[]) removeAll(array, toRemove);
5918     }
5919 
5920     /**
5921      * <p>Removes the elements at the specified positions from the specified array.
5922      * All remaining elements are shifted to the left.</p>
5923      *
5924      * <p>This method returns a new array with the same elements of the input
5925      * array except those at the specified positions. The component
5926      * type of the returned array is always the same as that of the input
5927      * array.</p>
5928      *
5929      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5930      * will be thrown, because in that case no valid index can be specified.</p>
5931      *
5932      * <pre>
5933      * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
5934      * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
5935      * </pre>
5936      *
5937      * @param array   the array to remove the element from, may not be {@code null}
5938      * @param indices the positions of the elements to be removed
5939      * @return A new array containing the existing elements except those
5940      *         at the specified positions.
5941      * @throws IndexOutOfBoundsException if any index is out of range
5942      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5943      * @since 3.0.1
5944      */
5945     public static boolean[] removeAll(final boolean[] array, final int... indices) {
5946         return (boolean[]) removeAll((Object) array, clone(indices));
5947     }
5948 
5949     /**
5950      * <p>Removes occurrences of specified elements, in specified quantities,
5951      * from the specified array. All subsequent elements are shifted left.
5952      * For any element-to-be-removed specified in greater quantities than
5953      * contained in the original array, no change occurs beyond the
5954      * removal of the existing matching items.</p>
5955      *
5956      * <p>This method returns a new array with the same elements of the input
5957      * array except for the earliest-encountered occurrences of the specified
5958      * elements. The component type of the returned array is always the same
5959      * as that of the input array.</p>
5960      *
5961      * <pre>
5962      * ArrayUtils.removeElements(null, true, false)               = null
5963      * ArrayUtils.removeElements([], true, false)                 = []
5964      * ArrayUtils.removeElements([true], false, false)            = [true]
5965      * ArrayUtils.removeElements([true, false], true, true)       = [false]
5966      * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
5967      * ArrayUtils.removeElements([true, false, true], true, true) = [false]
5968      * </pre>
5969      *
5970      * @param array  the array to remove the element from, may be {@code null}
5971      * @param values the elements to be removed
5972      * @return A new array containing the existing elements except the
5973      *         earliest-encountered occurrences of the specified elements.
5974      * @since 3.0.1
5975      */
5976     public static boolean[] removeElements(final boolean[] array, final boolean... values) {
5977         if (isEmpty(array) || isEmpty(values)) {
5978             return clone(array);
5979         }
5980         final HashMap<Boolean, MutableInt> occurrences = new HashMap<Boolean, MutableInt>(2); // only two possible values here
5981         for (final boolean v : values) {
5982             final Boolean boxed = Boolean.valueOf(v);
5983             final MutableInt count = occurrences.get(boxed);
5984             if (count == null) {
5985                 occurrences.put(boxed, new MutableInt(1));
5986             } else {
5987                 count.increment();
5988             }
5989         }
5990         final BitSet toRemove = new BitSet();
5991         for (final Map.Entry<Boolean, MutableInt> e : occurrences.entrySet()) {
5992             final Boolean v = e.getKey();
5993             int found = 0;
5994             for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5995                 found = indexOf(array, v.booleanValue(), found);
5996                 if (found < 0) {
5997                     break;
5998                 }
5999                 toRemove.set(found++);
6000             }
6001         }
6002         return (boolean[]) removeAll(array, toRemove);
6003     }
6004 
6005     /**
6006      * Removes multiple array elements specified by index.
6007      * @param array source
6008      * @param indices to remove, WILL BE SORTED--so only clones of user-owned arrays!
6009      * @return new array of same type minus elements specified by unique values of {@code indices}
6010      * @since 3.0.1
6011      */
6012     // package protected for access by unit tests
6013     static Object removeAll(final Object array, final int... indices) {
6014         final int length = getLength(array);
6015         int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
6016 
6017         if (isNotEmpty(indices)) {
6018             Arrays.sort(indices);
6019 
6020             int i = indices.length;
6021             int prevIndex = length;
6022             while (--i >= 0) {
6023                 final int index = indices[i];
6024                 if (index < 0 || index >= length) {
6025                     throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
6026                 }
6027                 if (index >= prevIndex) {
6028                     continue;
6029                 }
6030                 diff++;
6031                 prevIndex = index;
6032             }
6033         }
6034         final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
6035         if (diff < length) {
6036             int end = length; // index just after last copy
6037             int dest = length - diff; // number of entries so far not copied
6038             for (int i = indices.length - 1; i >= 0; i--) {
6039                 final int index = indices[i];
6040                 if (end - index > 1) { // same as (cp > 0)
6041                     final int cp = end - index - 1;
6042                     dest -= cp;
6043                     System.arraycopy(array, index + 1, result, dest, cp);
6044                     // Afer this copy, we still have room for dest items.
6045                 }
6046                 end = index;
6047             }
6048             if (end > 0) {
6049                 System.arraycopy(array, 0, result, 0, end);
6050             }
6051         }
6052         return result;
6053     }
6054 
6055     /**
6056      * Removes multiple array elements specified by indices.
6057      * 
6058      * @param array source
6059      * @param indices to remove
6060      * @return new array of same type minus elements specified by the set bits in {@code indices}
6061      * @since 3.2
6062      */
6063     // package protected for access by unit tests
6064     static Object removeAll(final Object array, final BitSet indices) {
6065         final int srcLength = ArrayUtils.getLength(array);
6066         // No need to check maxIndex here, because method only currently called from removeElements()
6067         // which guarantee to generate on;y valid bit entries.
6068 //        final int maxIndex = indices.length();
6069 //        if (maxIndex > srcLength) { 
6070 //            throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
6071 //        }
6072         final int removals = indices.cardinality(); // true bits are items to remove
6073         final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
6074         int srcIndex=0;
6075         int destIndex=0;
6076         int count;
6077         int set;
6078         while((set = indices.nextSetBit(srcIndex)) != -1){
6079             count = set - srcIndex;
6080             if (count > 0) {
6081                 System.arraycopy(array, srcIndex, result, destIndex, count);
6082                 destIndex += count;
6083             }
6084             srcIndex = indices.nextClearBit(set);
6085         }
6086         count = srcLength - srcIndex;
6087         if (count > 0) {
6088             System.arraycopy(array, srcIndex, result, destIndex, count);            
6089         }
6090         return result;
6091     }
6092 
6093     /**
6094      * <p>This method checks whether the provided array is sorted according to the class's 
6095      * {@code compareTo} method.</p>
6096      *
6097      * @param array the array to check
6098      * @param <T> the datatype of the array to check, it must implement {@code Comparable}
6099      * @return whether the array is sorted
6100      * @since 3.4
6101      */
6102     public static <T extends Comparable<? super T>> boolean isSorted(final T[] array) {
6103         return isSorted(array, new Comparator<T>() {
6104             @Override
6105             public int compare(T o1, T o2) {
6106                 return o1.compareTo(o2);
6107             }
6108         });
6109     }
6110    
6111 
6112     /**
6113      * <p>This method checks whether the provided array is sorted according to the provided {@code Comparator}.</p>
6114      *
6115      * @param array the array to check
6116      * @param comparator the {@code Comparator} to compare over
6117      * @param <T> the datatype of the array
6118      * @return whether the array is sorted
6119      * @since 3.4
6120      */
6121     public static <T> boolean isSorted(final T[] array, final Comparator<T> comparator) {
6122         if (comparator == null) {
6123             throw new IllegalArgumentException("Comparator should not be null.");
6124         }
6125         
6126         if(array == null || array.length < 2) {
6127             return true;
6128         }
6129 
6130         T previous = array[0];
6131         final int n = array.length;
6132         for(int i = 1; i < n; i++) {
6133             final T current = array[i];
6134             if (comparator.compare(previous, current) > 0) {
6135                 return false;
6136             }
6137 
6138             previous = current;
6139         }
6140         return true;
6141     }
6142 
6143     /**
6144      * <p>This method checks whether the provided array is sorted according to natural ordering.</p>
6145      *
6146      * @param array the array to check
6147      * @return whether the array is sorted according to natural ordering
6148      * @since 3.4
6149      */
6150     public static boolean isSorted(int[] array) {
6151         if(array == null || array.length < 2) {
6152             return true;
6153         }
6154 
6155         int previous = array[0];
6156         final int n = array.length;
6157         for(int i = 1; i < n; i++) {
6158             final int current = array[i];
6159             if(NumberUtils.compare(previous, current) > 0) {
6160                 return false;
6161             }
6162 
6163             previous = current;
6164         }
6165         return true;
6166     }
6167 
6168     /**
6169      * <p>This method checks whether the provided array is sorted according to natural ordering.</p>
6170      *
6171      * @param array the array to check
6172      * @return whether the array is sorted according to natural ordering
6173      * @since 3.4
6174      */
6175     public static boolean isSorted(long[] array) {
6176         if(array == null || array.length < 2) {
6177             return true;
6178         }
6179 
6180         long previous = array[0];
6181         final int n = array.length;
6182         for(int i = 1; i < n; i++) {
6183             final long current = array[i];
6184             if(NumberUtils.compare(previous, current) > 0) {
6185                 return false;
6186             }
6187 
6188             previous = current;
6189         }
6190         return true;
6191     }
6192 
6193     /**
6194      * <p>This method checks whether the provided array is sorted according to natural ordering.</p>
6195      *
6196      * @param array the array to check
6197      * @return whether the array is sorted according to natural ordering
6198      * @since 3.4
6199      */
6200     public static boolean isSorted(short[] array) {
6201         if(array == null || array.length < 2) {
6202             return true;
6203         }
6204 
6205         short previous = array[0];
6206         final int n = array.length;
6207         for(int i = 1; i < n; i++) {
6208             final short current = array[i];
6209             if(NumberUtils.compare(previous, current) > 0) {
6210                 return false;
6211             }
6212 
6213             previous = current;
6214         }
6215         return true;
6216     }
6217 
6218     /**
6219      * <p>This method checks whether the provided array is sorted according to natural ordering.</p>
6220      *
6221      * @param array the array to check
6222      * @return whether the array is sorted according to natural ordering
6223      * @since 3.4
6224      */
6225     public static boolean isSorted(final double[] array) {
6226         if(array == null || array.length < 2) {
6227             return true;
6228         }
6229 
6230         double previous = array[0];
6231         final int n = array.length;
6232         for(int i = 1; i < n; i++) {
6233             final double current = array[i];
6234             if(Double.compare(previous, current) > 0) {
6235                 return false;
6236             }
6237 
6238             previous = current;
6239         }
6240         return true;
6241     }
6242 
6243     /**
6244      * <p>This method checks whether the provided array is sorted according to natural ordering.</p>
6245      *
6246      * @param array the array to check
6247      * @return whether the array is sorted according to natural ordering
6248      * @since 3.4
6249      */
6250     public static boolean isSorted(final float[] array) {
6251         if(array == null || array.length < 2) {
6252             return true;
6253         }
6254 
6255         float previous = array[0];
6256         final int n = array.length;
6257         for(int i = 1; i < n; i++) {
6258             final float current = array[i];
6259             if(Float.compare(previous, current) > 0) {
6260                 return false;
6261             }
6262 
6263             previous = current;
6264         }
6265         return true;
6266     }
6267 
6268     /**
6269      * <p>This method checks whether the provided array is sorted according to natural ordering.</p>
6270      *
6271      * @param array the array to check
6272      * @return whether the array is sorted according to natural ordering
6273      * @since 3.4
6274      */
6275     public static boolean isSorted(byte[] array) {
6276         if(array == null || array.length < 2) {
6277             return true;
6278         }
6279 
6280         byte previous = array[0];
6281         final int n = array.length;
6282         for(int i = 1; i < n; i++) {
6283             final byte current = array[i];
6284             if(NumberUtils.compare(previous, current) > 0) {
6285                 return false;
6286             }
6287 
6288             previous = current;
6289         }
6290         return true;
6291     }
6292 
6293     /**
6294      * <p>This method checks whether the provided array is sorted according to natural ordering.</p>
6295      *
6296      * @param array the array to check
6297      * @return whether the array is sorted according to natural ordering
6298      * @since 3.4
6299      */
6300     public static boolean isSorted(char[] array) {
6301         if(array == null || array.length < 2) {
6302             return true;
6303         }
6304 
6305         char previous = array[0];
6306         final int n = array.length;
6307         for(int i = 1; i < n; i++) {
6308             final char current = array[i];
6309             if(CharUtils.compare(previous, current) > 0) {
6310                 return false;
6311             }
6312 
6313             previous = current;
6314         }
6315         return true;
6316     }
6317 
6318     /**
6319      * <p>This method checks whether the provided array is sorted according to natural ordering
6320      * ({@code false} before {@code true}).</p>
6321      *
6322      * @param array the array to check
6323      * @return whether the array is sorted according to natural ordering
6324      * @since 3.4
6325      */
6326     public static boolean isSorted(boolean[] array) {
6327         if(array == null || array.length < 2) {
6328             return true;
6329         }
6330 
6331         boolean previous = array[0];
6332         final int n = array.length;
6333         for(int i = 1; i < n; i++) {
6334             final boolean current = array[i];
6335             if(BooleanUtils.compare(previous, current) > 0) {
6336                 return false;
6337             }
6338 
6339             previous = current;
6340         }
6341         return true;
6342     }
6343 }